/** * Copyright (c) 2017-2018 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author David Sehnal * @author Alexander Rose */ import { Entities } from '../common'; import { CoarseElementData, CoarsedElementKeys } from '../coarse'; function getElementKey(map: Map, 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>, key: number) { if (map.has(key)) return map.get(key)!; const ret = new Map(); map.set(key, ret); return ret; } function createLookUp(entities: Entities, chain: Map>, seq: Map>) { const getEntKey = entities.getEntityIndex; const findChainKey: CoarsedElementKeys['findChainKey'] = (e, c) => { const eKey = getEntKey(e); if (eKey < 0) return -1; const cm = chain.get(eKey)!; if (!cm.has(c)) return -1; return cm.get(c)!; } const findSequenceKey: CoarsedElementKeys['findSequenceKey'] = (e, c, s) => { const eKey = getEntKey(e); if (eKey < 0) return -1; const cm = chain.get(eKey); if (cm === undefined) return -1 const cKey = cm.get(c) if (cKey === undefined) return -1 const sm = seq.get(cKey)! if (!sm.has(s)) return -1; return sm.get(s)! } return { findChainKey, findSequenceKey }; } function missingEntity(k: string) { throw new Error(`Missing entity entry for entity id '${k}'.`); } function missingModel(k: string) { throw new Error(`Missing entity entry for model id '${k}'.`); } export function getCoarseKeys(data: CoarseElementData, modelIndex: (id: number) => number, entities: Entities): CoarsedElementKeys { const { model_id, entity_id, asym_id, seq_id_begin, seq_id_end, count, chainSegments } = data; const seqMaps = new Map>(); const chainMaps = new Map>(), chainCounter = { index: 0 }; const chainKey = new Int32Array(count); const entityKey = new Int32Array(count); const modelKey = new Int32Array(count); for (let i = 0; i < count; i++) { entityKey[i] = entities.getEntityIndex(entity_id.value(i)); if (entityKey[i] < 0) missingEntity(entity_id.value(i)); modelKey[i] = modelIndex(model_id.value(i)); if (modelKey[i] < 0) missingModel('' + model_id.value(i)); } for (let cI = 0; cI < chainSegments.count; cI++) { const start = chainSegments.segments[cI], end = chainSegments.segments[cI + 1]; const map = getElementSubstructureKeyMap(chainMaps, entityKey[start]); const key = getElementKey(map, asym_id.value(start), chainCounter); for (let i = start; i < end; i++) chainKey[i] = key; // create seq_id map for the ranges defined by seq_id_begin and seq_id_end const seqMap: Map = new Map() seqMaps.set(key, seqMap) for (let i = start; i < end; i++) { const seqStart = seq_id_begin.value(i) const seqEnd = seq_id_end.value(i) for (let j = seqStart; j <= seqEnd; j++) { seqMap.set(j, i) } } } const { findChainKey, findSequenceKey } = createLookUp(entities, chainMaps, seqMaps); return { chainKey, entityKey, modelKey, findSequenceKey, findChainKey }; }