coarse-keys.ts 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  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. function getElementKey(map: Map<string, number>, key: string, counter: { index: number }) {
  10. if (map.has(key)) return map.get(key)!;
  11. const ret = counter.index++;
  12. map.set(key, ret);
  13. return ret;
  14. }
  15. function getElementSubstructureKeyMap(map: Map<number, Map<string, number>>, key: number) {
  16. if (map.has(key)) return map.get(key)!;
  17. const ret = new Map<string, number>();
  18. map.set(key, ret);
  19. return ret;
  20. }
  21. function createLookUp(entities: Entities, chain: Map<number, Map<string, number>>, seq: Map<number, Map<number, number>>) {
  22. const getEntKey = entities.getEntityIndex;
  23. const findChainKey: CoarsedElementKeys['findChainKey'] = (e, c) => {
  24. const eKey = getEntKey(e);
  25. if (eKey < 0) return -1;
  26. const cm = chain.get(eKey)!;
  27. if (!cm.has(c)) return -1;
  28. return cm.get(c)!;
  29. }
  30. const findSequenceKey: CoarsedElementKeys['findSequenceKey'] = (e, c, s) => {
  31. const eKey = getEntKey(e);
  32. if (eKey < 0) return -1;
  33. const cm = chain.get(eKey);
  34. if (cm === undefined) return -1
  35. const cKey = cm.get(c)
  36. if (cKey === undefined) return -1
  37. const sm = seq.get(cKey)!
  38. if (!sm.has(s)) return -1;
  39. return sm.get(s)!
  40. }
  41. return { findChainKey, findSequenceKey };
  42. }
  43. function missingEntity(k: string) {
  44. throw new Error(`Missing entity entry for entity id '${k}'.`);
  45. }
  46. function missingModel(k: string) {
  47. throw new Error(`Missing entity entry for model id '${k}'.`);
  48. }
  49. export function getCoarseKeys(data: CoarseElementData, modelIndex: (id: number) => number, entities: Entities): CoarsedElementKeys {
  50. const { model_id, entity_id, asym_id, seq_id_begin, seq_id_end, count, chainSegments } = data;
  51. const seqMaps = new Map<number, Map<number, number>>();
  52. const chainMaps = new Map<number, Map<string, number>>(), chainCounter = { index: 0 };
  53. const chainKey = new Int32Array(count);
  54. const entityKey = new Int32Array(count);
  55. const modelKey = new Int32Array(count);
  56. for (let i = 0; i < count; i++) {
  57. entityKey[i] = entities.getEntityIndex(entity_id.value(i));
  58. if (entityKey[i] < 0) missingEntity(entity_id.value(i));
  59. modelKey[i] = modelIndex(model_id.value(i));
  60. if (modelKey[i] < 0) missingModel('' + model_id.value(i));
  61. }
  62. for (let cI = 0; cI < chainSegments.count; cI++) {
  63. const start = chainSegments.segments[cI], end = chainSegments.segments[cI + 1];
  64. const map = getElementSubstructureKeyMap(chainMaps, entityKey[start]);
  65. const key = getElementKey(map, asym_id.value(start), chainCounter);
  66. for (let i = start; i < end; i++) chainKey[i] = key;
  67. // create seq_id map for the ranges defined by seq_id_begin and seq_id_end
  68. const seqMap: Map<number, number> = new Map()
  69. seqMaps.set(key, seqMap)
  70. for (let i = start; i < end; i++) {
  71. const seqStart = seq_id_begin.value(i)
  72. const seqEnd = seq_id_end.value(i)
  73. for (let j = seqStart; j <= seqEnd; j++) {
  74. seqMap.set(j, i)
  75. }
  76. }
  77. }
  78. const { findChainKey, findSequenceKey } = createLookUp(entities, chainMaps, seqMaps);
  79. return { chainKey, entityKey, modelKey, findSequenceKey, findChainKey };
  80. }