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

hierarchy keys

parent 1d765bfb
No related branches found
No related tags found
No related merge requests found
...@@ -109,7 +109,7 @@ namespace Column { ...@@ -109,7 +109,7 @@ namespace Column {
export default Column; export default Column;
function createFirstIndexMapOfColumn<T>(c: Column<T>): Map<T, number> | undefined { function createFirstIndexMapOfColumn<T>(c: Column<T>): Map<T, number> {
const map = new Map<T, number>(); const map = new Map<T, number>();
for (let i = 0, _i = c.rowCount; i < _i; i++) { for (let i = 0, _i = c.rowCount; i < _i; i++) {
const v = c.value(i); const v = c.value(i);
......
...@@ -94,7 +94,7 @@ class SegmentIterator implements Iterator<Segs.Segment> { ...@@ -94,7 +94,7 @@ class SegmentIterator implements Iterator<Segs.Segment> {
} }
} }
export function segments(segs: Segmentation, set: OrderedSet, range?: Interval) { export function segments(segs: Segmentation, set: OrderedSet, segment?: Segs.Segment) {
const int = typeof range !== 'undefined' ? range : Interval.ofBounds(0, OrderedSet.size(set)); const int = typeof segment !== 'undefined' ? Interval.ofBounds(segment.start, segment.end) : Interval.ofBounds(0, OrderedSet.size(set));
return new SegmentIterator(segs.segments, set, int); return new SegmentIterator(segs.segments, set, int);
} }
\ No newline at end of file
...@@ -20,7 +20,7 @@ namespace Segmentation { ...@@ -20,7 +20,7 @@ namespace Segmentation {
export const projectValue: (segs: Segmentation, set: OrderedSet, value: number) => Interval = Impl.projectValue as any; export const projectValue: (segs: Segmentation, set: OrderedSet, value: number) => Interval = Impl.projectValue as any;
// Segment iterator that mutates a single segment object to mark all the segments. // Segment iterator that mutates a single segment object to mark all the segments.
export const transientSegments: (segs: Segmentation, set: OrderedSet, range?: Interval) => Iterator<Segment> = Impl.segments as any; export const transientSegments: (segs: Segmentation, set: OrderedSet, segment?: Segment) => Iterator<Segment> = Impl.segments as any;
} }
interface Segmentation { interface Segmentation {
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
import Column from '../../../mol-base/collections/column' import Column from '../../../mol-base/collections/column'
import Table from '../../../mol-base/collections/table' import Table from '../../../mol-base/collections/table'
import Segmentation from '../../../mol-base/collections/integer/segmentation'
import { Schema as mmCIF } from '../../../mol-io/reader/cif/schema/mmcif' import { Schema as mmCIF } from '../../../mol-io/reader/cif/schema/mmcif'
const _esCache = Object.create(null); const _esCache = Object.create(null);
...@@ -35,7 +36,7 @@ export const ResiduesSchema = { ...@@ -35,7 +36,7 @@ export const ResiduesSchema = {
pdbx_PDB_ins_code: mmCIF.atom_site.pdbx_PDB_ins_code pdbx_PDB_ins_code: mmCIF.atom_site.pdbx_PDB_ins_code
}; };
export interface Residues extends Table<typeof AtomsSchema> { } export interface Residues extends Table<typeof ResiduesSchema> { }
export const ChainsSchema = { export const ChainsSchema = {
label_asym_id: mmCIF.atom_site.label_asym_id, label_asym_id: mmCIF.atom_site.label_asym_id,
...@@ -57,10 +58,15 @@ export interface HierarchyData { ...@@ -57,10 +58,15 @@ export interface HierarchyData {
entities: Entities entities: Entities
} }
export interface HierarchySegmentation {
residues: Segmentation,
chains: Segmentation
}
export interface HierarchyKeys { export interface HierarchyKeys {
// indicate whether the keys form an increasing sequence (in other words, the residues are sorted). // indicate whether the keys form an increasing sequence (in other words, the residues are sorted).
// monotonous sequences enable for example faster secodnary structure assignment. // monotonous sequences enable for example faster secodnary structure assignment.
isMonotonous: number, isMonotonous: boolean,
// assign a key to each residue index. // assign a key to each residue index.
residue: ArrayLike<number>, residue: ArrayLike<number>,
...@@ -71,8 +77,8 @@ export interface HierarchyKeys { ...@@ -71,8 +77,8 @@ export interface HierarchyKeys {
entity: ArrayLike<number>, entity: ArrayLike<number>,
findEntity(id: string): number, findEntity(id: string): number,
findChain(entityId: string, label_asym_id: string): number, findChain(entityId: string, auth_asym_id: string): number,
findResidue(entityId: string, label_asym_id: string, label_comp_id: string, label_seq_id: number, pdbx_PDB_ins_code: string): number findResidue(entityId: string, auth_asym_id: string, auth_comp_id: string, auth_seq_id: number, pdbx_PDB_ins_code: string): number
} }
export interface Hierarchy extends HierarchyData { export interface Hierarchy extends HierarchyData {
......
...@@ -4,11 +4,102 @@ ...@@ -4,11 +4,102 @@
* @author David Sehnal <david.sehnal@gmail.com> * @author David Sehnal <david.sehnal@gmail.com>
*/ */
import { HierarchyData, HierarchyKeys } from '../properties/hierarchy' import Column from '../../../mol-base/collections/column'
import { HierarchyData, HierarchySegmentation, HierarchyKeys } from '../properties/hierarchy'
import Segmentation from '../../../mol-base/collections/integer/segmentation'
import Interval from '../../../mol-base/collections/integer/interval'
function create(data: HierarchyData): HierarchyKeys { function getResidueId(comp_id: string, seq_id: number, ins_code: string) {
return `${comp_id} ${seq_id} ${ins_code}`;
}
function getElementKey(map: Map<string, number>, key: string, counter: { index: number }) {
if (map.has(key)) return map.get(key)!;
const ret = counter.index++;
map.set(key, ret);
return ret;
}
function getElementSubstructureKeyMap(map: Map<number, Map<string, number>>, key: number) {
if (map.has(key)) return map.get(key)!;
const ret = new Map<string, number>();
map.set(key, ret);
return ret;
}
function createLookUp(entity: Map<string, number>, chain: Map<number, Map<string, number>>, residue: Map<number, Map<string, number>>) {
const findEntity: HierarchyKeys['findEntity'] = (id) => entity.has(id) ? entity.get(id)! : -1;
const findChain: HierarchyKeys['findChain'] = (e, c) => {
if (!entity.has(e)) return -1;
const cm = chain.get(entity.get(e)!)!;
if (!cm.has(c)) return -1;
return cm.get(c)!;
}
const findResidue: HierarchyKeys['findResidue'] = (e, c, name, seq, ins) => {
if (!entity.has(e)) return -1;
const cm = chain.get(entity.get(e)!)!;
if (!cm.has(c)) return -1;
const rm = residue.get(cm.get(c)!)!
const id = getResidueId(name, seq, ins);
if (!rm.has(id)) return -1;
return rm.get(id)!;
}
return { findEntity, findChain, findResidue };
}
function isMonotonous(xs: ArrayLike<number>) {
for (let i = 1, _i = xs.length; i < _i; i++) {
if (xs[i] < xs[i - 1]) return false;
}
return true;
}
function create(data: HierarchyData, segments: HierarchySegmentation): HierarchyKeys {
const { chains, residues, entities } = data;
const entityMap = Column.createFirstIndexMap(entities.id);
const chainMaps = new Map<number, Map<string, number>>(), chainCounter = { index: 0 };
const residueMaps = new Map<number, Map<string, number>>(), residueCounter = { index: 0 };
const residueKey = new Int32Array(residues._rowCount);
const chainKey = new Int32Array(chains._rowCount);
const entityKey = new Int32Array(chains._rowCount);
const { auth_comp_id, auth_seq_id, pdbx_PDB_ins_code } = data.residues;
const { label_entity_id, auth_asym_id } = data.chains;
const chainsIt = Segmentation.transientSegments(segments.chains, Interval.ofBounds(0, data.atoms._rowCount));
while (chainsIt.hasNext) {
const chainSegment = chainsIt.move();
const residuesIt = Segmentation.transientSegments(segments.residues, Interval.ofBounds(chainSegment.start, chainSegment.end));
const cI = chainSegment.index;
const eKey = entityMap.get(label_entity_id.value(cI)) || 0;
const chainMap = getElementSubstructureKeyMap(chainMaps, eKey);
const cKey = getElementKey(chainMap, auth_asym_id.value(cI), chainCounter);
chainKey[cI] = cKey;
entityKey[cI] = eKey;
const residueMap = getElementSubstructureKeyMap(residueMaps, cKey);
while (residuesIt.hasNext) {
const rI = residuesIt.move().index;
const residueId = getResidueId(auth_comp_id.value(rI), auth_seq_id.value(rI), pdbx_PDB_ins_code.value(rI));
residueKey[rI] = getElementKey(residueMap, residueId, residueCounter);
}
}
const { findEntity, findChain, findResidue } = createLookUp(entityMap, chainMaps, residueMaps);
return 0 as any; return {
isMonotonous: isMonotonous(entityKey) && isMonotonous(chainKey) && isMonotonous(residueKey),
residue: residueKey,
chain: chainKey,
entity: entityKey,
findEntity,
findChain,
findResidue
};
} }
export default create; export default create;
\ No newline at end of file
...@@ -284,7 +284,56 @@ export function testSegments() { ...@@ -284,7 +284,56 @@ export function testSegments() {
} }
} }
Build.run(); export namespace ObjectVsMap {
function objCreate(keys: string[]) {
const m = Object.create(null);
m.x = 0;
delete m.x;
for (let i = 0, _i = keys.length; i < _i; i++) {
m[keys[i]] = i * i;
}
return m;
}
function mapCreate(keys: string[]) {
const m = new Map<string, number>();
for (let i = 0, _i = keys.length; i < _i; i++) {
m.set(keys[i], i * i);
}
return m;
}
function objQuery(keys: string[], n: number, obj: any) {
let ret = 0;
for (let i = 0; i < n; i++) ret += obj[keys[i % n]];
return ret;
}
function mapQuery(keys: string[], n: number, map: Map<string, number>) {
let ret = 0;
for (let i = 0; i < n; i++) ret += map.get(keys[i % n])!;
return ret;
}
export function run() {
const suite = new B.Suite();
const keys: string[] = [];
for (let i = 0; i < 1000; i++) keys[i] = 'k' + i;
const N = 100000;
const obj = objCreate(keys);
const map = mapCreate(keys);
suite
.add('c obj', () => objCreate(keys))
.add('c map', () => mapCreate(keys))
.add('q obj', () => objQuery(keys, N, obj))
.add('q map', () => mapQuery(keys, N, map))
.on('cycle', (e: any) => console.log(String(e.target)))
.run();
}
}
ObjectVsMap.run();
//testSegments(); //testSegments();
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment