nucleotide.ts 3.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. /**
  2. * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author Alexander Rose <alexander.rose@weirdbyte.de>
  5. */
  6. import { Unit, StructureElement, Structure } from 'mol-model/structure';
  7. import { getNucleotideElements } from 'mol-model/structure/structure/util/nucleotide';
  8. import { Loci, EmptyLoci } from 'mol-model/loci';
  9. import { OrderedSet, Interval } from 'mol-data/int';
  10. import { LocationIterator } from 'mol-geo/util/location-iterator';
  11. import { PickingId } from 'mol-geo/geometry/picking';
  12. import { StructureGroup } from 'mol-repr/structure/units-visual';
  13. import { getResidueLoci } from './common';
  14. export namespace NucleotideLocationIterator {
  15. export function fromGroup(group: Unit.SymmetryGroup): LocationIterator {
  16. const u = group.units[0]
  17. const nucleotideElementIndices = Unit.isAtomic(u) ? getNucleotideElements(u) : []
  18. const groupCount = nucleotideElementIndices.length
  19. const instanceCount = group.units.length
  20. const location = StructureElement.create()
  21. const getLocation = (groupIndex: number, instanceIndex: number) => {
  22. const unit = group.units[instanceIndex]
  23. location.unit = unit
  24. location.element = nucleotideElementIndices[groupIndex]
  25. return location
  26. }
  27. return LocationIterator(groupCount, instanceCount, getLocation)
  28. }
  29. }
  30. export function getNucleotideElementLoci(pickingId: PickingId, structureGroup: StructureGroup, id: number) {
  31. const { objectId, instanceId, groupId } = pickingId
  32. if (id === objectId) {
  33. const { structure, group } = structureGroup
  34. const unit = group.units[instanceId]
  35. if (Unit.isAtomic(unit)) {
  36. return getResidueLoci(structure, unit, unit.polymerElements[groupId])
  37. }
  38. }
  39. return EmptyLoci
  40. }
  41. export function eachNucleotideElement(loci: Loci, structureGroup: StructureGroup, apply: (interval: Interval) => boolean) {
  42. let changed = false
  43. if (!StructureElement.isLoci(loci)) return false
  44. const { structure, group } = structureGroup
  45. if (!Structure.areEquivalent(loci.structure, structure)) return false
  46. const unit = group.units[0]
  47. if (!Unit.isAtomic(unit)) return false
  48. const { nucleotideElements, model, elements } = unit
  49. const { index, offsets } = model.atomicHierarchy.residueAtomSegments
  50. const { traceElementIndex } = model.atomicHierarchy.derived.residue
  51. const groupCount = nucleotideElements.length
  52. for (const e of loci.elements) {
  53. const unitIdx = group.unitIndexMap.get(e.unit.id)
  54. const eUnit = e.unit
  55. if (unitIdx !== undefined && Unit.isAtomic(eUnit)) {
  56. // TODO optimized implementation for intervals
  57. OrderedSet.forEach(e.indices, v => {
  58. const rI = index[elements[v]]
  59. const unitIndexMin = OrderedSet.findPredecessorIndex(elements, offsets[rI])
  60. const unitIndexMax = OrderedSet.findPredecessorIndex(elements, offsets[rI + 1] - 1)
  61. const unitIndexInterval = Interval.ofRange(unitIndexMin, unitIndexMax)
  62. if (!OrderedSet.isSubset(e.indices, unitIndexInterval)) return
  63. const eI = traceElementIndex[rI]
  64. const idx = OrderedSet.indexOf(eUnit.nucleotideElements, eI)
  65. if (idx !== -1) {
  66. if (apply(Interval.ofSingleton(unitIdx * groupCount + idx))) changed = true
  67. }
  68. })
  69. }
  70. }
  71. return changed
  72. }