Skip to content
Snippets Groups Projects
Commit 5dc0a5e5 authored by David Sehnal's avatar David Sehnal
Browse files

Updated carb representation (indicate whether it has a ring; geometry is a single property)

parent 494728e2
No related branches found
No related tags found
No related merge requests found
...@@ -47,50 +47,53 @@ async function createCarbohydrateSymbolMesh(ctx: RuntimeContext, structure: Stru ...@@ -47,50 +47,53 @@ async function createCarbohydrateSymbolMesh(ctx: RuntimeContext, structure: Stru
const linkParams = { radiusTop: 0.4, radiusBottom: 0.4 } const linkParams = { radiusTop: 0.4, radiusBottom: 0.4 }
for (let i = 0, il = carbohydrates.elements.length; i < il; ++i) { for (let i = 0, il = carbohydrates.elements.length; i < il; ++i) {
const c = carbohydrates.elements[i] const c = carbohydrates.elements[i];
if (!c.hasRing) continue;
const cGeo = c.geometry!
const shapeType = getSaccharideShape(c.component.type) const shapeType = getSaccharideShape(c.component.type)
switch (shapeType) { switch (shapeType) {
case SaccharideShapes.FilledSphere: case SaccharideShapes.FilledSphere:
builder.addIcosahedron(c.center, radius, 2) builder.addIcosahedron(cGeo.center, radius, 2)
break; break;
case SaccharideShapes.FilledCube: case SaccharideShapes.FilledCube:
centerAlign(c.center, c.normal, c.direction) centerAlign(cGeo.center, cGeo.normal, cGeo.direction)
builder.addBox(t, { width: side, height: side, depth: side }) builder.addBox(t, { width: side, height: side, depth: side })
break; break;
case SaccharideShapes.CrossedCube: case SaccharideShapes.CrossedCube:
// TODO split // TODO split
centerAlign(c.center, c.normal, c.direction) centerAlign(cGeo.center, cGeo.normal, cGeo.direction)
builder.addBox(t, { width: side, height: side, depth: side }) builder.addBox(t, { width: side, height: side, depth: side })
break; break;
case SaccharideShapes.FilledCone: case SaccharideShapes.FilledCone:
Vec3.scaleAndAdd(p1, c.center, c.direction, radius) Vec3.scaleAndAdd(p1, cGeo.center, cGeo.direction, radius)
Vec3.scaleAndSub(p2, c.center, c.direction, radius) Vec3.scaleAndSub(p2, cGeo.center, cGeo.direction, radius)
builder.addCylinder(p1, p2, 1, coneParams) builder.addCylinder(p1, p2, 1, coneParams)
break break
case SaccharideShapes.DevidedCone: case SaccharideShapes.DevidedCone:
// TODO split // TODO split
Vec3.scaleAndAdd(p1, c.center, c.direction, radius) Vec3.scaleAndAdd(p1, cGeo.center, cGeo.direction, radius)
Vec3.scaleAndSub(p2, c.center, c.direction, radius) Vec3.scaleAndSub(p2, cGeo.center, cGeo.direction, radius)
builder.addCylinder(p1, p2, 1, coneParams) builder.addCylinder(p1, p2, 1, coneParams)
break break
case SaccharideShapes.FlatBox: case SaccharideShapes.FlatBox:
centerAlign(c.center, c.normal, c.direction) centerAlign(cGeo.center, cGeo.normal, cGeo.direction)
builder.addBox(t, { width: side, height: side / 2, depth: side }) builder.addBox(t, { width: side, height: side / 2, depth: side })
break break
case SaccharideShapes.FilledStar: case SaccharideShapes.FilledStar:
centerAlign(c.center, c.normal, c.direction) centerAlign(cGeo.center, cGeo.normal, cGeo.direction)
builder.addStar(t, { outerRadius: side, innerRadius: side / 2, thickness: side / 2, pointCount: 5 }) builder.addStar(t, { outerRadius: side, innerRadius: side / 2, thickness: side / 2, pointCount: 5 })
break break
case SaccharideShapes.FilledDiamond: case SaccharideShapes.FilledDiamond:
case SaccharideShapes.DividedDiamond: case SaccharideShapes.DividedDiamond:
case SaccharideShapes.FlatDiamond: case SaccharideShapes.FlatDiamond:
case SaccharideShapes.Pentagon: case SaccharideShapes.Pentagon:
centerAlign(c.center, c.normal, c.direction) centerAlign(cGeo.center, cGeo.normal, cGeo.direction)
builder.addBox(t, { width: side, height: side, depth: 0.5 }) builder.addBox(t, { width: side, height: side, depth: 0.5 })
break break
case SaccharideShapes.FlatHexagon: case SaccharideShapes.FlatHexagon:
default: default:
centerAlign(c.center, c.normal, c.direction) centerAlign(cGeo.center, cGeo.normal, cGeo.direction)
builder.addBox(t, { width: side, height: side, depth: 0.1 }) builder.addBox(t, { width: side, height: side, depth: 0.1 })
break break
} }
...@@ -98,14 +101,14 @@ async function createCarbohydrateSymbolMesh(ctx: RuntimeContext, structure: Stru ...@@ -98,14 +101,14 @@ async function createCarbohydrateSymbolMesh(ctx: RuntimeContext, structure: Stru
for (let i = 0, il = carbohydrates.links.length; i < il; ++i) { for (let i = 0, il = carbohydrates.links.length; i < il; ++i) {
const l = carbohydrates.links[i] const l = carbohydrates.links[i]
const centerA = carbohydrates.elements[l.carbohydrateIndexA].center const centerA = carbohydrates.elements[l.carbohydrateIndexA].geometry!.center
const centerB = carbohydrates.elements[l.carbohydrateIndexB].center const centerB = carbohydrates.elements[l.carbohydrateIndexB].geometry!.center
builder.addCylinder(centerA, centerB, 0.5, linkParams) builder.addCylinder(centerA, centerB, 0.5, linkParams)
} }
for (let i = 0, il = carbohydrates.terminalLinks.length; i < il; ++i) { for (let i = 0, il = carbohydrates.terminalLinks.length; i < il; ++i) {
const tl = carbohydrates.terminalLinks[i] const tl = carbohydrates.terminalLinks[i]
const center = carbohydrates.elements[tl.carbohydrateIndex].center const center = carbohydrates.elements[tl.carbohydrateIndex].geometry!.center
tl.elementUnit.conformation.position(tl.elementUnit.elements[tl.elementIndex], p) tl.elementUnit.conformation.position(tl.elementUnit.elements[tl.elementIndex], p)
if (tl.fromCarbohydrate) { if (tl.fromCarbohydrate) {
builder.addCylinder(center, p, 0.5, linkParams) builder.addCylinder(center, p, 0.5, linkParams)
......
...@@ -90,22 +90,22 @@ export function computeCarbohydrates(structure: Structure): Carbohydrates { ...@@ -90,22 +90,22 @@ export function computeCarbohydrates(structure: Structure): Carbohydrates {
const terminalLinks: CarbohydrateTerminalLink[] = [] const terminalLinks: CarbohydrateTerminalLink[] = []
const elements: CarbohydrateElement[] = [] const elements: CarbohydrateElement[] = []
const elementsMap = new Map<string, number>() const elementsWithRingMap = new Map<string, number>()
function elementKey(residueIndex: number, unitId: number) { function elementKey(residueIndex: number, unitId: number) {
return `${residueIndex}|${unitId}` return `${residueIndex}|${unitId}`
} }
function fixLinkDirection(iA: number, iB: number) { function fixLinkDirection(iA: number, iB: number) {
Vec3.sub(elements[iA].direction, elements[iB].center, elements[iA].center) Vec3.sub(elements[iA].geometry!.direction, elements[iB].geometry!.center, elements[iA].geometry!.center)
Vec3.normalize(elements[iA].direction, elements[iA].direction) Vec3.normalize(elements[iA].geometry!.direction, elements[iA].geometry!.direction)
} }
const tmpV = Vec3.zero() const tmpV = Vec3.zero()
function fixTerminalLinkDirection(iA: number, indexB: number, unitB: Unit.Atomic) { function fixTerminalLinkDirection(iA: number, indexB: number, unitB: Unit.Atomic) {
const pos = unitB.conformation.position const pos = unitB.conformation.position, geo = elements[iA].geometry!;
Vec3.sub(elements[iA].direction, pos(unitB.elements[indexB], tmpV), elements[iA].center) Vec3.sub(geo.direction, pos(unitB.elements[indexB], tmpV), geo.center)
Vec3.normalize(elements[iA].direction, elements[iA].direction) Vec3.normalize(geo.direction, geo.direction)
} }
// get carbohydrate elements and carbohydrate links induced by intra-residue bonds // get carbohydrate elements and carbohydrate links induced by intra-residue bonds
...@@ -140,7 +140,10 @@ export function computeCarbohydrates(structure: Structure): Carbohydrates { ...@@ -140,7 +140,10 @@ export function computeCarbohydrates(structure: Structure): Carbohydrates {
const sugarRings = sugarResidueMap.get(residueIndex); const sugarRings = sugarResidueMap.get(residueIndex);
if (!sugarRings || !sugarRings.length) { if (!sugarRings || !sugarRings.length) {
console.warn(`No ring found for carbohydrate on residue with index ${residueIndex}, unit ${unit.id}. Residue skipped.`); elements.push({
hasRing: false,
unit, residueIndex, component: saccharideComp
})
continue; continue;
} }
...@@ -158,8 +161,12 @@ export function computeCarbohydrates(structure: Structure): Carbohydrates { ...@@ -158,8 +161,12 @@ export function computeCarbohydrates(structure: Structure): Carbohydrates {
const elementIndex = elements.length const elementIndex = elements.length
ringElements.push(elementIndex) ringElements.push(elementIndex)
elementsMap.set(elementKey(residueIndex, unit.id), elementIndex) elementsWithRingMap.set(elementKey(residueIndex, unit.id), elementIndex)
elements.push({ center, normal, direction, unit, residueIndex, component: saccharideComp }) elements.push({
geometry: { center, normal, direction, },
hasRing: true,
unit, residueIndex, component: saccharideComp
})
} }
// add carbohydrate links induced by intra-residue bonds // add carbohydrate links induced by intra-residue bonds
...@@ -195,8 +202,8 @@ export function computeCarbohydrates(structure: Structure): Carbohydrates { ...@@ -195,8 +202,8 @@ export function computeCarbohydrates(structure: Structure): Carbohydrates {
pairBonds.getBonds(indexA).forEach(bondInfo => { pairBonds.getBonds(indexA).forEach(bondInfo => {
const { unitA, unitB } = pairBonds const { unitA, unitB } = pairBonds
const indexB = bondInfo.indexB const indexB = bondInfo.indexB
const elementIndexA = elementsMap.get(elementKey(getResidueIndex(indexA, unitA), unitA.id)) const elementIndexA = elementsWithRingMap.get(elementKey(getResidueIndex(indexA, unitA), unitA.id))
const elementIndexB = elementsMap.get(elementKey(getResidueIndex(indexB, unitB), unitB.id)) const elementIndexB = elementsWithRingMap.get(elementKey(getResidueIndex(indexB, unitB), unitB.id))
if (elementIndexA !== undefined && elementIndexB !== undefined) { if (elementIndexA !== undefined && elementIndexB !== undefined) {
if (getAtomId(unitA, indexA).startsWith('C1')) { if (getAtomId(unitA, indexA).startsWith('C1')) {
......
...@@ -23,11 +23,11 @@ export interface CarbohydrateTerminalLink { ...@@ -23,11 +23,11 @@ export interface CarbohydrateTerminalLink {
} }
export interface CarbohydrateElement { export interface CarbohydrateElement {
readonly center: Vec3, // geometry is only defined if at least one ring is present.
readonly normal: Vec3, readonly geometry?: { readonly center: Vec3, readonly normal: Vec3, readonly direction: Vec3 },
readonly direction: Vec3, readonly hasRing: boolean,
readonly unit: Unit.Atomic readonly unit: Unit.Atomic,
readonly residueIndex: ResidueIndex readonly residueIndex: ResidueIndex,
readonly component: SaccharideComponent readonly component: SaccharideComponent
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment