structure.ts 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. /**
  2. * Copyright (c) 2017 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author David Sehnal <david.sehnal@gmail.com>
  5. */
  6. import { OrderedSet, Iterator } from 'mol-base/collections/integer'
  7. import UniqueArray from 'mol-base/collections/unique-array'
  8. import { Model, Format } from '../model'
  9. import Unit from './unit'
  10. import Operator from './operator'
  11. import AtomSet from './atom/set'
  12. import Atom from './atom'
  13. interface Structure extends Readonly<{
  14. units: { readonly [id: number]: Unit },
  15. atoms: AtomSet
  16. }> { }
  17. namespace Structure {
  18. export const Empty = { units: {}, atoms: AtomSet.Empty };
  19. export function create(units: Structure['units'], atoms: AtomSet): Structure {
  20. return { units, atoms };
  21. }
  22. export function ofData(format: Format) {
  23. const models = Model.create(format);
  24. return models.map(ofModel);
  25. }
  26. export function ofModel(model: Model): Structure {
  27. const chains = model.hierarchy.chainSegments;
  28. const builder = Builder();
  29. for (let c = 0; c < chains.count; c++) {
  30. const unit = Unit.create(model, Operator.Identity);
  31. builder.addUnit(unit);
  32. builder.addAtoms(unit.id, OrderedSet.ofBounds(chains.segments[c], chains.segments[c + 1]));
  33. }
  34. return builder.getStructure();
  35. }
  36. export interface Builder {
  37. addUnit(unit: Unit): void,
  38. addAtoms(unitId: number, atoms: OrderedSet): void,
  39. getStructure(): Structure,
  40. readonly atomCount: number
  41. }
  42. class BuilderImpl implements Builder {
  43. private units = Object.create(null);
  44. private atoms = Object.create(null);
  45. atomCount = 0;
  46. addUnit(unit: Unit) { this.units[unit.id] = unit; }
  47. addAtoms(unitId: number, atoms: OrderedSet) { this.atoms[unitId] = atoms; this.atomCount += OrderedSet.size(atoms); }
  48. getStructure(): Structure { return this.atomCount > 0 ? Structure.create(this.units, AtomSet.create(this.atoms)) : Empty; }
  49. }
  50. export function Builder(): Builder { return new BuilderImpl(); }
  51. /** Transient = location gets overwritten when move() is called. */
  52. export function atomLocationsTransient(s: Structure): Iterator<Atom.Location> {
  53. const l = Atom.Location();
  54. const update = Atom.updateLocation;
  55. return Iterator.map(AtomSet.atoms(s.atoms), a => update(s, l, a));
  56. }
  57. export function getModels(s: Structure) {
  58. const arr = UniqueArray.create<Model['id'], Model>();
  59. for (const k of Object.keys(s.units)) {
  60. const u = s.units[+k];
  61. UniqueArray.add(arr, u.model.id, u.model);
  62. }
  63. return arr.array;
  64. }
  65. // TODO: "lift" atom set operators?
  66. // TODO: "diff"
  67. }
  68. export default Structure