coarse-keys.ts 3.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. /**
  2. * Copyright (c) 2017-2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author David Sehnal <david.sehnal@gmail.com>
  5. * @author Alexander Rose <alexander.rose@weirdbyte.de>
  6. */
  7. import { Entities } from '../common';
  8. import { CoarseElementData, CoarsedElementKeys } from '../coarse';
  9. import { ChainIndex, ElementIndex, EntityIndex } from '../../indexing';
  10. function getElementKey(map: Map<string, number>, key: string, counter: { index: number }) {
  11. if (map.has(key)) return map.get(key)!;
  12. const ret = counter.index++;
  13. map.set(key, ret);
  14. return ret;
  15. }
  16. function getElementSubstructureKeyMap(map: Map<number, Map<string, number>>, key: number) {
  17. if (map.has(key)) return map.get(key)!;
  18. const ret = new Map<string, number>();
  19. map.set(key, ret);
  20. return ret;
  21. }
  22. function createLookUp(entities: Entities, chain: Map<number, Map<string, number>>, seq: Map<number, Map<number, number>>) {
  23. const getEntKey = entities.getEntityIndex;
  24. const findChainKey: CoarsedElementKeys['findChainKey'] = (e, c) => {
  25. const eKey = getEntKey(e);
  26. if (eKey < 0) return -1 as ChainIndex;
  27. const cm = chain.get(eKey)!;
  28. if (!cm.has(c)) return -1 as ChainIndex;
  29. return cm.get(c)! as ChainIndex;
  30. }
  31. // TODO consider implementing as binary search
  32. const findSequenceKey: CoarsedElementKeys['findSequenceKey'] = (e, c, s) => {
  33. const eKey = getEntKey(e);
  34. if (eKey < 0) return -1 as ElementIndex;
  35. const cm = chain.get(eKey);
  36. if (cm === undefined) return -1 as ElementIndex
  37. const cKey = cm.get(c)
  38. if (cKey === undefined) return -1 as ElementIndex
  39. const sm = seq.get(cKey)!
  40. if (!sm.has(s)) return -1 as ElementIndex;
  41. return sm.get(s)! as ElementIndex
  42. }
  43. return { findChainKey, findSequenceKey };
  44. }
  45. function missingEntity(k: string) {
  46. throw new Error(`Missing entity entry for entity id '${k}'.`);
  47. }
  48. export function getCoarseKeys(data: CoarseElementData, entities: Entities): CoarsedElementKeys {
  49. const { entity_id, asym_id, seq_id_begin, seq_id_end, count, chainElementSegments } = data;
  50. const seqMaps = new Map<number, Map<number, number>>();
  51. const chainMaps = new Map<number, Map<string, number>>(), chainCounter = { index: 0 };
  52. const chainKey = new Int32Array(count) as any as ChainIndex[];
  53. const entityKey = new Int32Array(count) as any as EntityIndex[];
  54. for (let i = 0; i < count; i++) {
  55. entityKey[i] = entities.getEntityIndex(entity_id.value(i));
  56. if (entityKey[i] < 0) missingEntity(entity_id.value(i));
  57. }
  58. for (let cI = 0; cI < chainElementSegments.count; cI++) {
  59. const start = chainElementSegments.offsets[cI], end = chainElementSegments.offsets[cI + 1];
  60. const map = getElementSubstructureKeyMap(chainMaps, entityKey[start]);
  61. const key = getElementKey(map, asym_id.value(start), chainCounter) as ChainIndex;
  62. for (let i = start; i < end; i++) chainKey[i] = key;
  63. // create seq_id map for the ranges defined by seq_id_begin and seq_id_end
  64. const seqMap: Map<number, number> = new Map()
  65. seqMaps.set(key, seqMap)
  66. for (let i = start; i < end; i++) {
  67. const seqStart = seq_id_begin.value(i)
  68. const seqEnd = seq_id_end.value(i)
  69. for (let j = seqStart; j <= seqEnd; j++) {
  70. seqMap.set(j, i)
  71. }
  72. }
  73. }
  74. const { findChainKey, findSequenceKey } = createLookUp(entities, chainMaps, seqMaps);
  75. return { chainKey, entityKey, findSequenceKey, findChainKey };
  76. }