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

Added IntGraph and using it for IntraUnitBonds

parent 38031818
No related branches found
No related tags found
No related merge requests found
......@@ -76,22 +76,15 @@ export function printBonds(structure: Structure) {
if (!Unit.isAtomic(unit)) continue;
const elements = unit.elements;
const { count, offset, neighbor } = unit.bonds;
const { a, b } = unit.bonds;
const { model } = unit;
if (!count) continue;
if (!a.length) continue;
for (let j = 0; j < offset.length - 1; ++j) {
const start = offset[j];
const end = offset[j + 1];
if (end <= start) continue;
const aI = elements[j];
for (let _bI = start; _bI < end; _bI++) {
const bI = elements[neighbor[_bI]];
console.log(`${atomLabel(model, aI)} -- ${atomLabel(model, bI)}`);
}
for (let bI = 0, _bI = a.length; bI < _bI; bI++) {
const x = a[bI], y = b[bI];
if (x >= y) continue;
console.log(`${atomLabel(model, elements[x])} -- ${atomLabel(model, elements[y])}`);
}
}
}
......@@ -153,7 +146,7 @@ async function run(mmcif: mmCIF_Database) {
printSequence(models[0]);
printIHMModels(models[0]);
printUnits(structure);
// printBonds(structure);
printBonds(structure);
printSecStructure(models[0]);
}
......
/**
* Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author David Sehnal <david.sehnal@gmail.com>
*/
export * from './graph/int/graph'
\ No newline at end of file
/**
* Copyright (c) 2017-2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author David Sehnal <david.sehnal@gmail.com>
*/
import { IntGraph } from '../int/graph';
describe('IntGraph', () => {
const vc = 3;
const xs = [0, 1, 2];
const ys = [1, 2, 0];
const _prop = [10, 11, 12];
const builder = new IntGraph.EdgeBuilder(vc, xs, ys);
const prop: number[] = new Array(builder.slotCount);
for (let i = 0; i < builder.edgeCount; i++) {
builder.addNextEdge();
builder.assignProperty(prop, _prop[i]);
}
const graph = builder.createGraph({ prop });
it('triangle-edgeCount', () => expect(graph.edgeCount).toBe(3));
it('triangle-vertexEdgeCounts', () => {
expect(graph.getVertexEdgeCount(0)).toBe(2);
expect(graph.getVertexEdgeCount(1)).toBe(2);
expect(graph.getVertexEdgeCount(2)).toBe(2);
});
it('triangle-propAndEdgeIndex', () => {
const prop = graph.prop;
expect(prop[graph.getEdgeIndex(0, 1)]).toBe(10);
expect(prop[graph.getEdgeIndex(1, 2)]).toBe(11);
expect(prop[graph.getEdgeIndex(2, 0)]).toBe(12);
});
});
\ No newline at end of file
/**
* Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author David Sehnal <david.sehnal@gmail.com>
*/
/**
* Represent a graph using vertex adjacency list.
*
* Edges of the i-th vertex are stored in the arrays a and b
* for indices in the range [offset[i], offset[i+1]).
*
* Edge properties are indexed same as in the arrays a and b.
*/
type IntGraph<EdgeProperties extends object = { }> = {
readonly offset: ArrayLike<number>,
readonly a: ArrayLike<number>,
readonly b: ArrayLike<number>,
readonly vertexCount: number,
readonly edgeCount: number,
/**
* Get the edge index between i-th and j-th vertex.
* -1 if the edge does not exist.
*
* Because the a and b arrays contains each edge twice,
* this always returns the smaller of the indices.
*/
getEdgeIndex(i: number, j: number): number,
getVertexEdgeCount(i: number): number
} & EdgeProperties
namespace IntGraph {
class Impl implements IntGraph<any> {
readonly vertexCount: number;
getEdgeIndex(i: number, j: number): number {
let a, b;
if (i < j) { a = i; b = j; }
else { a = j; b = i; }
for (let t = this.offset[a], _t = this.offset[a + 1]; t < _t; t++) {
if (this.b[t] === b) return t;
}
return -1;
}
getVertexEdgeCount(i: number): number {
return this.offset[i + 1] - this.offset[i];
}
constructor(public offset: ArrayLike<number>, public a: ArrayLike<number>, public b: ArrayLike<number>, public edgeCount: number, props?: any) {
this.vertexCount = offset.length - 1;
if (props) {
for (const p of Object.keys(props)) {
(this as any)[p] = props[p];
}
}
}
}
export function create<EdgeProps extends object = { }>(offset: ArrayLike<number>, a: ArrayLike<number>, b: ArrayLike<number>, edgeCount: number, edgeProps?: EdgeProps): IntGraph<EdgeProps> {
return new Impl(offset, a, b, edgeCount, edgeProps) as IntGraph<EdgeProps>;
}
export class EdgeBuilder {
private bucketFill: Int32Array;
private current = 0;
private curA: number = 0;
private curB: number = 0;
offsets: Int32Array;
edgeCount: number;
/** the size of the A and B arrays */
slotCount: number;
a: Int32Array;
b: Int32Array;
createGraph<EdgeProps extends object = { }>(edgeProps?: EdgeProps) {
return create(this.offsets, this.a, this.b, this.edgeCount, edgeProps);
}
/**
* @example
* const property = new Int32Array(builder.slotCount);
* for (let i = 0; i < builder.edgeCount; i++) {
* builder.addNextEdge();
* builder.assignProperty(property, srcProp[i]);
* }
* return builder.createGraph({ property });
*/
addNextEdge() {
const a = this.xs[this.current], b = this.ys[this.current];
const oa = this.offsets[a] + this.bucketFill[a];
const ob = this.offsets[b] + this.bucketFill[b];
this.a[oa] = a;
this.b[oa] = b;
this.bucketFill[a]++;
this.a[ob] = b;
this.b[ob] = a;
this.bucketFill[b]++;
this.current++;
this.curA = oa;
this.curB = ob;
}
assignProperty<T>(prop: { [i: number]: T }, value: T) {
prop[this.curA] = value;
prop[this.curB] = value;
}
constructor(public vertexCount: number, public xs: ArrayLike<number>, public ys: ArrayLike<number>) {
this.edgeCount = xs.length;
this.offsets = new Int32Array(this.vertexCount + 1);
this.bucketFill = new Int32Array(this.vertexCount);
const bucketSizes = new Int32Array(this.vertexCount);
for (let i = 0, _i = this.xs.length; i < _i; i++) bucketSizes[this.xs[i]]++;
for (let i = 0, _i = this.ys.length; i < _i; i++) bucketSizes[this.ys[i]]++;
let offset = 0;
for (let i = 0; i < this.vertexCount; i++) {
this.offsets[i] = offset;
offset += bucketSizes[i];
}
this.offsets[this.vertexCount] = offset;
this.slotCount = offset;
this.a = new Int32Array(offset);
this.b = new Int32Array(offset);
}
}
}
export { IntGraph }
\ No newline at end of file
- Support for FASTA etc..
- Mapping/properties for 'structure'
\ No newline at end of file
File moved
/**
* Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author David Sehnal <david.sehnal@gmail.com>
*/
// import { Column } from 'mol-data/db'
// TODO
interface Sequence {
}
namespace Sequence {
export const enum Kind {
Protein = 'protein',
RNA = 'RNA',
DNA = 'DNA',
Generic = 'generic'
}
export type ProteinAlphabet = 'X'
export type RnaAlphabet = 'X'
export type DnaAlphabet = 'C'
export type GenericAlphabet = 'X'
export interface Base<K extends Kind, Alphabet extends string> {
readonly kind: K,
readonly sequence: ReadonlyArray<Alphabet>
}
}
export { Sequence }
......@@ -8,6 +8,7 @@ import { BondType, ElementSymbol } from '../../../model/types'
import { IntraUnitBonds } from './intra-data'
import { StructConn, ComponentBondInfo } from '../../../model/formats/mmcif/bonds'
import Unit from '../../unit'
import { IntGraph } from 'mol-math/graph';
export interface BondComputationParameters {
maxHbondLength: number,
......@@ -62,48 +63,17 @@ function isHydrogen(i: number) {
return i === H_ID;
}
function computePerAtomBonds(atomA: number[], atomB: number[], _order: number[], _flags: number[], atomCount: number) {
const bucketSizes = new Int32Array(atomCount);
const bucketOffsets = new Int32Array(atomCount + 1) as any as number[];
const bucketFill = new Int32Array(atomCount);
for (const i of atomA) bucketSizes[i]++;
for (const i of atomB) bucketSizes[i]++;
let offset = 0;
for (let i = 0; i < atomCount; i++) {
bucketOffsets[i] = offset;
offset += bucketSizes[i];
function getGraph(atomA: number[], atomB: number[], _order: number[], _flags: number[], atomCount: number): IntraUnitBonds {
const builder = new IntGraph.EdgeBuilder(atomCount, atomA, atomB);
const flags = new Uint16Array(builder.slotCount);
const order = new Int8Array(builder.slotCount);
for (let i = 0, _i = builder.edgeCount; i < _i; i++) {
builder.addNextEdge();
builder.assignProperty(flags, _flags[i]);
builder.assignProperty(order, _order[i]);
}
bucketOffsets[atomCount] = offset;
const neighbor = new Int32Array(offset) as any as number[];
const flags = new Uint16Array(offset) as any as number[];
const order = new Int8Array(offset) as any as number[];
for (let i = 0, _i = atomA.length; i < _i; i++) {
const a = atomA[i], b = atomB[i], f = _flags[i], o = _order[i];
const oa = bucketOffsets[a] + bucketFill[a];
const ob = bucketOffsets[b] + bucketFill[b];
neighbor[oa] = b;
flags[oa] = f;
order[oa] = o;
bucketFill[a]++;
neighbor[ob] = a;
flags[ob] = f;
order[ob] = o;
bucketFill[b]++;
}
return {
offsets: bucketOffsets,
neighbor,
flags,
order
};
return builder.createGraph({ flags, order });
}
function _computeBonds(unit: Unit.Atomic, params: BondComputationParameters): IntraUnitBonds {
......@@ -231,15 +201,7 @@ function _computeBonds(unit: Unit.Atomic, params: BondComputationParameters): In
}
}
const bonds = computePerAtomBonds(atomA, atomB, order, flags, atomCount);
return {
offset: bonds.offsets,
neighbor: bonds.neighbor,
flags: bonds.flags,
order: bonds.order,
count: atomA.length
};
return getGraph(atomA, atomB, order, flags, atomCount);
}
function computeIntraUnitBonds(unit: Unit.Atomic, params?: Partial<BondComputationParameters>) {
......
......@@ -6,24 +6,13 @@
*/
import { BondType } from '../../../model/types'
import { IntGraph } from 'mol-math/graph';
interface IntraUnitBonds {
/**
* Where bonds for atom A start and end.
* Start offset at idx, end at idx + 1
*/
offset: ArrayLike<number>,
neighbor: ArrayLike<number>,
order: ArrayLike<number>,
flags: ArrayLike<BondType.Flag>,
count: number
}
type IntraUnitBonds = IntGraph<{ readonly order: ArrayLike<number>, readonly flags: ArrayLike<BondType.Flag> }>
namespace IntraUnitBonds {
export function createEmpty(): IntraUnitBonds {
return { offset: [], neighbor: [], order: [], flags: [], count: 0 }
return IntGraph.create([], [], [], 0, { flags: [], order: [] });
}
export function isCovalent(flags: number) {
return (flags & BondType.Flag.Covalent) !== 0;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment