Skip to content
Snippets Groups Projects
Commit 2476bf76 authored by Alexander Rose's avatar Alexander Rose
Browse files

Merge branch 'master' of https://github.com/molstar/molstar

parents 1c4a3972 d0a861d3
No related branches found
No related tags found
No related merge requests found
...@@ -6,4 +6,7 @@ ...@@ -6,4 +6,7 @@
"*.vert.ts": "glsl", "*.vert.ts": "glsl",
"*.gql.ts": "graphql" "*.gql.ts": "graphql"
}, },
"eslint.options": {
"ignorePattern": ["webpack.config.js", "scripts/*"],
}
} }
\ No newline at end of file
...@@ -240,22 +240,18 @@ const tmpVecD = Vec3() ...@@ -240,22 +240,18 @@ const tmpVecD = Vec3()
function getNormal(out: Vec3, info: Features.Info) { function getNormal(out: Vec3, info: Features.Info) {
const { unit, feature, offsets, members } = info const { unit, feature, offsets, members } = info
const { elements } = unit const { elements } = unit
const { x, y, z } = unit.model.atomicConformation
const i = offsets[feature] const i = offsets[feature]
const aI = elements[members[i]] info.unit.conformation.position(elements[members[i]], tmpVecA)
const bI = elements[members[i + 1]] info.unit.conformation.position(elements[members[i + 1]], tmpVecB)
const cI = elements[members[i + 2]] info.unit.conformation.position(elements[members[i + 2]], tmpVecC)
Vec3.set(tmpVecA, x[aI], y[aI], z[aI])
Vec3.set(tmpVecB, x[bI], y[bI], z[bI])
Vec3.set(tmpVecC, x[cI], y[cI], z[cI])
return Vec3.triangleNormal(out, tmpVecA, tmpVecB, tmpVecC) return Vec3.triangleNormal(out, tmpVecA, tmpVecB, tmpVecC)
} }
const getOffset = function (infoA: Features.Info, infoB: Features.Info, normal: Vec3) { const getOffset = function (infoA: Features.Info, infoB: Features.Info, normal: Vec3) {
Vec3.set(tmpVecA, infoA.x[infoA.feature], infoA.y[infoA.feature], infoA.z[infoA.feature]) Features.position(tmpVecA, infoA)
Vec3.set(tmpVecB, infoB.x[infoB.feature], infoB.y[infoB.feature], infoB.z[infoB.feature]) Features.position(tmpVecB, infoB)
Vec3.sub(tmpVecC, tmpVecA, tmpVecB) Vec3.sub(tmpVecC, tmpVecA, tmpVecB)
......
...@@ -65,12 +65,6 @@ function isMember(element: StructureElement.UnitIndex, info: Features.Info) { ...@@ -65,12 +65,6 @@ function isMember(element: StructureElement.UnitIndex, info: Features.Info) {
return false return false
} }
function setPosition(out: Vec3, info: Features.Info) {
Vec3.set(out, info.x[info.feature], info.y[info.feature], info.z[info.feature])
Vec3.transformMat4(out, out, info.unit.conformation.operator.matrix)
return out
}
const tmpVec = Vec3() const tmpVec = Vec3()
const tmpVecA = Vec3() const tmpVecA = Vec3()
const tmpVecB = Vec3() const tmpVecB = Vec3()
...@@ -81,8 +75,8 @@ function checkLineOfSight(structure: Structure, infoA: Features.Info, infoB: Fea ...@@ -81,8 +75,8 @@ function checkLineOfSight(structure: Structure, infoA: Features.Info, infoB: Fea
const indexA = infoA.members[infoA.offsets[featureA]] const indexA = infoA.members[infoA.offsets[featureA]]
const indexB = infoB.members[infoB.offsets[featureB]] const indexB = infoB.members[infoB.offsets[featureB]]
setPosition(tmpVecA, infoA) Features.position(tmpVecA, infoA)
setPosition(tmpVecB, infoB) Features.position(tmpVecB, infoB)
Vec3.scale(tmpVec, Vec3.add(tmpVec, tmpVecA, tmpVecB), 0.5) Vec3.scale(tmpVec, Vec3.add(tmpVec, tmpVecA, tmpVecB), 0.5)
const distMax = distFactor * MAX_LINE_OF_SIGHT_DISTANCE const distMax = distFactor * MAX_LINE_OF_SIGHT_DISTANCE
......
...@@ -161,6 +161,22 @@ namespace Features { ...@@ -161,6 +161,22 @@ namespace Features {
} }
} }
export function position(out: Vec3, info: Info) {
Vec3.set(out, info.x[info.feature], info.y[info.feature], info.z[info.feature])
Vec3.transformMat4(out, out, info.unit.conformation.operator.matrix)
return out
}
const tmpVecA = Vec3()
const tmpVecB = Vec3()
export function distance(infoA: Info, infoB: Info) {
const elementA = infoA.members[infoA.offsets[infoA.feature]]
const elementB = infoB.members[infoB.offsets[infoB.feature]]
infoA.unit.conformation.position(infoA.unit.elements[elementA], tmpVecA)
infoB.unit.conformation.position(infoB.unit.elements[elementB], tmpVecB)
return Vec3.distance(tmpVecA, tmpVecB)
}
export interface Provider { export interface Provider {
types: Set<FeatureType> types: Set<FeatureType>
add: (structure: Structure, unit: Unit.Atomic, featuresBuilder: FeaturesBuilder) => void add: (structure: Structure, unit: Unit.Atomic, featuresBuilder: FeaturesBuilder) => void
......
...@@ -68,8 +68,11 @@ function addUnitHydrogenDonors(structure: Structure, unit: Unit.Atomic, builder: ...@@ -68,8 +68,11 @@ function addUnitHydrogenDonors(structure: Structure, unit: Unit.Atomic, builder:
const { totalH } = getUnitValenceModel(structure, unit) const { totalH } = getUnitValenceModel(structure, unit)
const { elements } = unit const { elements } = unit
const { x, y, z } = unit.model.atomicConformation const { x, y, z } = unit.model.atomicConformation
const { elementAromaticRingIndices } = unit.rings
for (let i = 0 as StructureElement.UnitIndex, il = elements.length; i < il; ++i) { for (let i = 0 as StructureElement.UnitIndex, il = elements.length; i < il; ++i) {
if (elementAromaticRingIndices.has(i)) continue;
const element = typeSymbol(unit, i) const element = typeSymbol(unit, i)
if (( if ((
// include both nitrogen atoms in histidine due to // include both nitrogen atoms in histidine due to
...@@ -99,7 +102,7 @@ function addUnitWeakHydrogenDonors(structure: Structure, unit: Unit.Atomic, buil ...@@ -99,7 +102,7 @@ function addUnitWeakHydrogenDonors(structure: Structure, unit: Unit.Atomic, buil
( (
bondToElementCount(structure, unit, i, Elements.N) > 0 || bondToElementCount(structure, unit, i, Elements.N) > 0 ||
bondToElementCount(structure, unit, i, Elements.O) > 0 || bondToElementCount(structure, unit, i, Elements.O) > 0 ||
inAromaticRingWithElectronNegativeElement(structure, unit, i) inAromaticRingWithElectronNegativeElement(unit, i)
) )
) { ) {
builder.add(FeatureType.WeakHydrogenDonor, FeatureGroup.None, x[elements[i]], y[elements[i]], z[elements[i]], i) builder.add(FeatureType.WeakHydrogenDonor, FeatureGroup.None, x[elements[i]], y[elements[i]], z[elements[i]], i)
...@@ -107,27 +110,21 @@ function addUnitWeakHydrogenDonors(structure: Structure, unit: Unit.Atomic, buil ...@@ -107,27 +110,21 @@ function addUnitWeakHydrogenDonors(structure: Structure, unit: Unit.Atomic, buil
} }
} }
function inAromaticRingWithElectronNegativeElement(structure: Structure, unit: Unit.Atomic, index: StructureElement.UnitIndex) { function inAromaticRingWithElectronNegativeElement(unit: Unit.Atomic, index: StructureElement.UnitIndex) {
return false // TODO const { elementAromaticRingIndices, all } = unit.rings
// if (!a.isAromatic()) return false const ringIndices = elementAromaticRingIndices.get(index)
if (ringIndices === undefined) return false
// const ringData = a.residueType.getRings()
// if (!ringData) return false
// let hasElement = false for (let i = 0, il = ringIndices.length; i < il; ++i) {
// const rings = ringData.rings const ring = all[ringIndices[i]]
// rings.forEach(ring => { for (let j = 0, jl = ring.length; j < jl; ++j) {
// if (hasElement) return // already found one const element = typeSymbol(unit, ring[j])
// if (ring.some(idx => (a.index - a.residueAtomOffset) === idx)) { // in ring if (element === Elements.N || element === Elements.O) {
// hasElement = ring.some(idx => { return true
// const atomTypeId = a.residueType.atomTypeIdList[ idx ] }
// const number = a.atomMap.get(atomTypeId).number }
// return number === Elements.N || number === Elements.O }
// }) return false
// }
// })
// return hasElement
} }
/** /**
...@@ -137,12 +134,15 @@ function addUnitHydrogenAcceptors(structure: Structure, unit: Unit.Atomic, build ...@@ -137,12 +134,15 @@ function addUnitHydrogenAcceptors(structure: Structure, unit: Unit.Atomic, build
const { charge, implicitH, idealGeometry } = getUnitValenceModel(structure, unit) const { charge, implicitH, idealGeometry } = getUnitValenceModel(structure, unit)
const { elements } = unit const { elements } = unit
const { x, y, z } = unit.model.atomicConformation const { x, y, z } = unit.model.atomicConformation
const { elementAromaticRingIndices } = unit.rings
const add = (i: StructureElement.UnitIndex) => { const add = (i: StructureElement.UnitIndex) => {
builder.add(FeatureType.HydrogenAcceptor, FeatureGroup.None, x[elements[i]], y[elements[i]], z[elements[i]], i) builder.add(FeatureType.HydrogenAcceptor, FeatureGroup.None, x[elements[i]], y[elements[i]], z[elements[i]], i)
} }
for (let i = 0 as StructureElement.UnitIndex, il = elements.length; i < il; ++i) { for (let i = 0 as StructureElement.UnitIndex, il = elements.length; i < il; ++i) {
if (elementAromaticRingIndices.has(i)) continue;
const element = typeSymbol(unit, i) const element = typeSymbol(unit, i)
if (element === Elements.O) { if (element === Elements.O) {
// Basically assume all oxygen atoms are acceptors! // Basically assume all oxygen atoms are acceptors!
......
...@@ -8,7 +8,6 @@ ...@@ -8,7 +8,6 @@
import { Interactions } from './interactions'; import { Interactions } from './interactions';
import { InteractionType, InteractionFlag, InteractionsIntraContacts, FeatureType, InteractionsInterContacts } from './common'; import { InteractionType, InteractionFlag, InteractionsIntraContacts, FeatureType, InteractionsInterContacts } from './common';
import { Vec3 } from '../../../mol-math/linear-algebra';
import { Unit, Structure } from '../../../mol-model/structure'; import { Unit, Structure } from '../../../mol-model/structure';
import { Features } from './features'; import { Features } from './features';
...@@ -91,22 +90,17 @@ function hydrophobicRefiner(structure: Structure, interactions: Interactions): C ...@@ -91,22 +90,17 @@ function hydrophobicRefiner(structure: Structure, interactions: Interactions): C
} }
} }
const pA = Vec3()
const pB = Vec3()
function handleEdge(edge: number, infoA: Features.Info, infoB: Features.Info, map: Map<string, [number, number]>, set: (i: number) => void) { function handleEdge(edge: number, infoA: Features.Info, infoB: Features.Info, map: Map<string, [number, number]>, set: (i: number) => void) {
const elementA = infoA.members[infoA.offsets[infoA.feature]] const elementA = infoA.members[infoA.offsets[infoA.feature]]
const elementB = infoB.members[infoB.offsets[infoB.feature]] const elementB = infoB.members[infoB.offsets[infoB.feature]]
const residueA = infoA.unit.getResidueIndex(elementA) const residueA = infoA.unit.getResidueIndex(elementA)
const residueB = infoB.unit.getResidueIndex(elementB) const residueB = infoB.unit.getResidueIndex(elementB)
infoA.unit.conformation.position(infoA.unit.elements[elementA], pA)
infoB.unit.conformation.position(infoB.unit.elements[elementB], pB)
const dist = Vec3.distance(pA, pB)
const keyA = `${elementA}|${infoA.unit.id}|${residueB}|${infoB.unit.id}|A` const keyA = `${elementA}|${infoA.unit.id}|${residueB}|${infoB.unit.id}|A`
const keyB = `${elementB}|${infoB.unit.id}|${residueA}|${infoA.unit.id}|B` const keyB = `${elementB}|${infoB.unit.id}|${residueA}|${infoA.unit.id}|B`
const dist = Features.distance(infoA, infoB)
handleResidueContact(dist, edge, keyA, map, set) handleResidueContact(dist, edge, keyA, map, set)
handleResidueContact(dist, edge, keyB, map, set) handleResidueContact(dist, edge, keyB, map, set)
} }
......
...@@ -25,6 +25,7 @@ class UnitRings { ...@@ -25,6 +25,7 @@ class UnitRings {
private _byFingerprint?: ReadonlyMap<UnitRing.Fingerprint, ReadonlyArray<UnitRings.Index>>; private _byFingerprint?: ReadonlyMap<UnitRing.Fingerprint, ReadonlyArray<UnitRings.Index>>;
private _index?: { private _index?: {
readonly elementRingIndices: ReadonlyMap<StructureElement.UnitIndex, UnitRings.Index[]>, readonly elementRingIndices: ReadonlyMap<StructureElement.UnitIndex, UnitRings.Index[]>,
readonly elementAromaticRingIndices: ReadonlyMap<StructureElement.UnitIndex, UnitRings.Index[]>,
readonly ringComponentIndex: ReadonlyArray<UnitRings.ComponentIndex>, readonly ringComponentIndex: ReadonlyArray<UnitRings.ComponentIndex>,
readonly ringComponents: ReadonlyArray<ReadonlyArray<UnitRings.Index>> readonly ringComponents: ReadonlyArray<ReadonlyArray<UnitRings.Index>>
}; };
...@@ -32,7 +33,7 @@ class UnitRings { ...@@ -32,7 +33,7 @@ class UnitRings {
private get index() { private get index() {
if (this._index) return this._index; if (this._index) return this._index;
this._index = createIndex(this.all); this._index = createIndex(this.all, this.aromaticRings);
return this._index; return this._index;
} }
...@@ -42,11 +43,15 @@ class UnitRings { ...@@ -42,11 +43,15 @@ class UnitRings {
return this._byFingerprint; return this._byFingerprint;
} }
/** Maps atom index inside a Unit to the smallest ring index (an atom can be part of more than one ring) */ /** Maps atom index inside a Unit to ring indices (an atom can be part of more than one ring) */
get elementRingIndices() { get elementRingIndices() {
return this.index.elementRingIndices; return this.index.elementRingIndices;
} }
get elementAromaticRingIndices() {
return this.index.elementAromaticRingIndices;
}
/** Maps UnitRings.Index to index to ringComponents */ /** Maps UnitRings.Index to index to ringComponents */
get ringComponentIndex() { get ringComponentIndex() {
return this.index.ringComponentIndex; return this.index.ringComponentIndex;
......
...@@ -253,8 +253,9 @@ function buildFinderprint(elements: string[], offset: number) { ...@@ -253,8 +253,9 @@ function buildFinderprint(elements: string[], offset: number) {
type RingIndex = import('../rings').UnitRings.Index type RingIndex = import('../rings').UnitRings.Index
type RingComponentIndex = import('../rings').UnitRings.ComponentIndex type RingComponentIndex = import('../rings').UnitRings.ComponentIndex
export function createIndex(rings: ArrayLike<SortedArray<StructureElement.UnitIndex>>) { export function createIndex(rings: ArrayLike<SortedArray<StructureElement.UnitIndex>>, aromaticRings: ReadonlyArray<RingIndex>) {
const elementRingIndices: Map<StructureElement.UnitIndex, RingIndex[]> = new Map(); const elementRingIndices: Map<StructureElement.UnitIndex, RingIndex[]> = new Map();
const elementAromaticRingIndices: Map<StructureElement.UnitIndex, RingIndex[]> = new Map();
// for each ring atom, assign all rings that it is present in // for each ring atom, assign all rings that it is present in
for (let rI = 0 as RingIndex, _rI = rings.length; rI < _rI; rI++) { for (let rI = 0 as RingIndex, _rI = rings.length; rI < _rI; rI++) {
...@@ -266,6 +267,17 @@ export function createIndex(rings: ArrayLike<SortedArray<StructureElement.UnitIn ...@@ -266,6 +267,17 @@ export function createIndex(rings: ArrayLike<SortedArray<StructureElement.UnitIn
} }
} }
// for each ring atom, assign all aromatic rings that it is present in
for (let aI = 0, _aI = aromaticRings.length; aI < _aI; aI++) {
const rI = aromaticRings[aI]
const r = rings[rI];
for (let i = 0, _i = r.length; i < _i; i++) {
const e = r[i];
if (elementAromaticRingIndices.has(e)) elementAromaticRingIndices.get(e)!.push(rI);
else elementAromaticRingIndices.set(e, [rI]);
}
}
// create a graph where vertices are rings, edge if two rings share at least one atom // create a graph where vertices are rings, edge if two rings share at least one atom
const graph = new IntAdjacencyGraph.UniqueEdgeBuilder(rings.length); const graph = new IntAdjacencyGraph.UniqueEdgeBuilder(rings.length);
for (let rI = 0 as RingIndex, _rI = rings.length; rI < _rI; rI++) { for (let rI = 0 as RingIndex, _rI = rings.length; rI < _rI; rI++) {
...@@ -296,5 +308,5 @@ export function createIndex(rings: ArrayLike<SortedArray<StructureElement.UnitIn ...@@ -296,5 +308,5 @@ export function createIndex(rings: ArrayLike<SortedArray<StructureElement.UnitIn
ringComponents[ringComponentIndex[rI]].push(rI); ringComponents[ringComponentIndex[rI]].push(rI);
} }
return { elementRingIndices, ringComponentIndex, ringComponents }; return { elementRingIndices, elementAromaticRingIndices, ringComponentIndex, ringComponents };
} }
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment