/** * Copyright (c) 2018-2020 Mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author Alexander Rose */ import { Model } from '../../../mol-model/structure/model/model' import { Table } from '../../../mol-data/db' import { mmCIF_Schema } from '../../../mol-io/reader/cif/schema/mmcif'; import { Unit, CustomPropertyDescriptor } from '../../../mol-model/structure'; import { ElementIndex } from '../../../mol-model/structure/model/indexing'; import { FormatPropertyProvider } from '../../../mol-model-formats/structure/common/property'; export { ModelCrossLinkRestraint } interface ModelCrossLinkRestraint { getIndicesByElement: (element: ElementIndex, kind: Unit.Kind) => number[] data: Table } namespace ModelCrossLinkRestraint { export const Descriptor: CustomPropertyDescriptor = { name: 'ihm_cross_link_restraint', // TODO cifExport } export const Provider = FormatPropertyProvider.create(Descriptor) export function fromTable(table: Table, model: Model): ModelCrossLinkRestraint { const p1 = { entity_id: table.entity_id_1, asym_id: table.asym_id_1, seq_id: table.seq_id_1, atom_id: table.atom_id_1, } const p2: typeof p1 = { entity_id: table.entity_id_2, asym_id: table.asym_id_2, seq_id: table.seq_id_2, atom_id: table.atom_id_2, } function _add(map: Map, element: ElementIndex, row: number) { const indices = map.get(element) if (indices) indices.push(row) else map.set(element, [ row ]) } function add(row: number, ps: typeof p1) { const entityId = ps.entity_id.value(row) const asymId = ps.asym_id.value(row) const seqId = ps.seq_id.value(row) if (table.model_granularity.value(row) === 'by-atom') { const atomicElement = model.atomicHierarchy.index.findAtom({ auth_seq_id: seqId, label_asym_id: asymId, label_atom_id: ps.atom_id.value(row), label_entity_id: entityId, }) if (atomicElement >= 0) _add(atomicElementMap, atomicElement as ElementIndex, row) } else if (model.coarseHierarchy.isDefined) { const sphereElement = model.coarseHierarchy.spheres.findSequenceKey(entityId, asymId, seqId) if (sphereElement >= 0) { _add(sphereElementMap, sphereElement, row) } else { const gaussianElement = model.coarseHierarchy.gaussians.findSequenceKey(entityId, asymId, seqId) if (gaussianElement >= 0) _add(gaussianElementMap, gaussianElement, row) } } } function getMapByKind(kind: Unit.Kind) { switch (kind) { case Unit.Kind.Atomic: return atomicElementMap; case Unit.Kind.Spheres: return sphereElementMap; case Unit.Kind.Gaussians: return gaussianElementMap; } } /** map from atomic element to cross link indices */ const atomicElementMap: Map = new Map() /** map from sphere element to cross link indices */ const sphereElementMap: Map = new Map() /** map from gaussian element to cross link indices */ const gaussianElementMap: Map = new Map() const emptyIndexArray: number[] = []; for (let i = 0; i < table._rowCount; ++i) { add(i, p1) add(i, p2) } return { getIndicesByElement: (element: ElementIndex, kind: Unit.Kind) => { const map = getMapByKind(kind) const idx = map.get(element) return idx !== undefined ? idx : emptyIndexArray }, data: table } } }