diff --git a/src/mol-model/structure/model/formats/mmcif/pair-restraint.ts b/src/mol-model/structure/model/formats/mmcif/pair-restraint.ts index 5cfe9f4e3ed1147334b195d252bf156eed3541f9..40cec49d41786cc3576f29bca18c357e87cb715e 100644 --- a/src/mol-model/structure/model/formats/mmcif/pair-restraint.ts +++ b/src/mol-model/structure/model/formats/mmcif/pair-restraint.ts @@ -4,154 +4,5 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -// ihm_predicted_contact_restraint: { -// id: int, -// entity_id_1: str, -// entity_id_2: str, -// asym_id_1: str, -// asym_id_2: str, -// comp_id_1: str, -// comp_id_2: str, -// seq_id_1: int, -// seq_id_2: int, -// atom_id_1: str, -// atom_id_2: str, -// distance_upper_limit: float, -// probability: float, -// restraint_type: Aliased<'lower bound' | 'upper bound' | 'lower and upper bound'>(str), -// model_granularity: Aliased<'by-residue' | 'by-feature' | 'by-atom'>(str), -// dataset_list_id: int, -// software_id: int, -// }, -// ihm_cross_link_restraint: { -// id: int, -// group_id: int, -// entity_id_1: str, -// entity_id_2: str, -// asym_id_1: str, -// asym_id_2: str, -// comp_id_1: str, -// comp_id_2: str, -// seq_id_1: int, -// seq_id_2: int, -// atom_id_1: str, -// atom_id_2: str, -// restraint_type: Aliased<'harmonic' | 'upper bound' | 'lower bound'>(str), -// conditional_crosslink_flag: Aliased<'ALL' | 'ANY'>(str), -// model_granularity: Aliased<'by-residue' | 'by-feature' | 'by-atom'>(str), -// distance_threshold: float, -// psi: float, -// sigma_1: float, -// sigma_2: float, -// }, - -import Model from '../../model' -import { Table } from 'mol-data/db' -import { mmCIF_Schema } from 'mol-io/reader/cif/schema/mmcif'; -import { findAtomIndexByLabelName } from './util'; -import { Element, Unit } from '../../../structure'; - -function findAtomIndex(model: Model, entityId: string, asymId: string, compId: string, seqId: number, atomId: string) { - if (!model.atomicHierarchy.atoms.auth_atom_id.isDefined) return -1 - const residueIndex = model.atomicHierarchy.findResidueKey(entityId, compId, asymId, seqId, '') - if (residueIndex < 0) return -1 - return findAtomIndexByLabelName(model, residueIndex, atomId, '') as Element -} - -// function findElementIndex(model: Model, entityId: string, asymId: string, compId: string, seqId: number, atomId: string) { - -// } - -// function key(entityId: string, asymId: string, compId: string, seqId: number, atomId: string) { -// return `${entityId}|${asymId}|${compId}|${seqId}|${atomId}` -// } - -export interface IHMCrossLinkRestraint { - getIndicesByElement: (element: Element, kind: Unit.Kind) => number[] - data: Table<mmCIF_Schema['ihm_cross_link_restraint']> -} - -export namespace IHMCrossLinkRestraint { - export const PropName = '__CrossLinkRestraint__'; - export function fromModel(model: Model): IHMCrossLinkRestraint | undefined { - if (model.properties[PropName]) return model.properties[PropName] - - if (model.sourceData.kind !== 'mmCIF') return - const { ihm_cross_link_restraint } = model.sourceData.data; - if (!ihm_cross_link_restraint._rowCount) return - - const p1 = { - entity_id: ihm_cross_link_restraint.entity_id_1, - asym_id: ihm_cross_link_restraint.asym_id_1, - comp_id: ihm_cross_link_restraint.comp_id_1, - seq_id: ihm_cross_link_restraint.seq_id_1, - atom_id: ihm_cross_link_restraint.atom_id_1, - } - - const p2: typeof p1 = { - entity_id: ihm_cross_link_restraint.entity_id_2, - asym_id: ihm_cross_link_restraint.asym_id_2, - comp_id: ihm_cross_link_restraint.comp_id_2, - seq_id: ihm_cross_link_restraint.seq_id_2, - atom_id: ihm_cross_link_restraint.atom_id_2, - } - - function _add(map: Map<Element, number[]>, element: Element, 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 (ihm_cross_link_restraint.model_granularity.value(row) === 'by-atom') { - const atomicElement = findAtomIndex(model, entityId, asymId, ps.comp_id.value(row), seqId, ps.atom_id.value(row)) - if (atomicElement >= 0) _add(atomicElementMap, atomicElement as Element, row) - } else if (model.coarseHierarchy.isDefined) { - const sphereElement = model.coarseHierarchy.spheres.findSequenceKey(entityId, asymId, seqId) - if (sphereElement >= 0) { - _add(sphereElementMap, sphereElement as Element, row) - } else { - const gaussianElement = model.coarseHierarchy.gaussians.findSequenceKey(entityId, asymId, seqId) - if (gaussianElement >= 0) _add(gaussianElementMap, gaussianElement as Element, 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<Element, number[]> = new Map() - /** map from sphere element to cross link indices */ - const sphereElementMap: Map<Element, number[]> = new Map() - /** map from gaussian element to cross link indices */ - const gaussianElementMap: Map<Element, number[]> = new Map() - - const emptyIndexArray: number[] = []; - - for (let i = 0; i < ihm_cross_link_restraint._rowCount; ++i) { - add(i, p1) - add(i, p2) - } - - const crossLinkRestraint = { - getIndicesByElement: (element: Element, kind: Unit.Kind) => { - const map = getMapByKind(kind) - const idx = map.get(element) - return idx !== undefined ? idx : emptyIndexArray - }, - data: ihm_cross_link_restraint - } - model.properties[PropName] = crossLinkRestraint - return crossLinkRestraint - } -} \ No newline at end of file +export * from './pair-restraints/cross-links' +// export * from './pair-restraints/predicted-contacts' \ No newline at end of file diff --git a/src/mol-model/structure/model/formats/mmcif/pair-restraints/cross-links.ts b/src/mol-model/structure/model/formats/mmcif/pair-restraints/cross-links.ts new file mode 100644 index 0000000000000000000000000000000000000000..584a429ccb559cef0e7480f0db2b20734aaa13e0 --- /dev/null +++ b/src/mol-model/structure/model/formats/mmcif/pair-restraints/cross-links.ts @@ -0,0 +1,108 @@ +/** + * Copyright (c) 2018 Mol* contributors, licensed under MIT, See LICENSE file for more info. + * + * @author Alexander Rose <alexander.rose@weirdbyte.de> + */ + +import Model from '../../../model' +import { Table } from 'mol-data/db' +import { mmCIF_Schema } from 'mol-io/reader/cif/schema/mmcif'; +import { findAtomIndexByLabelName } from '../util'; +import { Element, Unit } from '../../../../structure'; + +function findAtomIndex(model: Model, entityId: string, asymId: string, compId: string, seqId: number, atomId: string) { + if (!model.atomicHierarchy.atoms.auth_atom_id.isDefined) return -1 + const residueIndex = model.atomicHierarchy.findResidueKey(entityId, compId, asymId, seqId, '') + if (residueIndex < 0) return -1 + return findAtomIndexByLabelName(model, residueIndex, atomId, '') as Element +} + +export interface IHMCrossLinkRestraint { + getIndicesByElement: (element: Element, kind: Unit.Kind) => number[] + data: Table<mmCIF_Schema['ihm_cross_link_restraint']> +} + +export namespace IHMCrossLinkRestraint { + export const PropName = '__CrossLinkRestraint__'; + export function fromModel(model: Model): IHMCrossLinkRestraint | undefined { + if (model._staticPropertyData[PropName]) return model._staticPropertyData[PropName] + + if (model.sourceData.kind !== 'mmCIF') return + const { ihm_cross_link_restraint } = model.sourceData.data; + if (!ihm_cross_link_restraint._rowCount) return + + const p1 = { + entity_id: ihm_cross_link_restraint.entity_id_1, + asym_id: ihm_cross_link_restraint.asym_id_1, + comp_id: ihm_cross_link_restraint.comp_id_1, + seq_id: ihm_cross_link_restraint.seq_id_1, + atom_id: ihm_cross_link_restraint.atom_id_1, + } + + const p2: typeof p1 = { + entity_id: ihm_cross_link_restraint.entity_id_2, + asym_id: ihm_cross_link_restraint.asym_id_2, + comp_id: ihm_cross_link_restraint.comp_id_2, + seq_id: ihm_cross_link_restraint.seq_id_2, + atom_id: ihm_cross_link_restraint.atom_id_2, + } + + function _add(map: Map<Element, number[]>, element: Element, 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 (ihm_cross_link_restraint.model_granularity.value(row) === 'by-atom') { + const atomicElement = findAtomIndex(model, entityId, asymId, ps.comp_id.value(row), seqId, ps.atom_id.value(row)) + if (atomicElement >= 0) _add(atomicElementMap, atomicElement as Element, row) + } else if (model.coarseHierarchy.isDefined) { + const sphereElement = model.coarseHierarchy.spheres.findSequenceKey(entityId, asymId, seqId) + if (sphereElement >= 0) { + _add(sphereElementMap, sphereElement as Element, row) + } else { + const gaussianElement = model.coarseHierarchy.gaussians.findSequenceKey(entityId, asymId, seqId) + if (gaussianElement >= 0) _add(gaussianElementMap, gaussianElement as Element, 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<Element, number[]> = new Map() + /** map from sphere element to cross link indices */ + const sphereElementMap: Map<Element, number[]> = new Map() + /** map from gaussian element to cross link indices */ + const gaussianElementMap: Map<Element, number[]> = new Map() + + const emptyIndexArray: number[] = []; + + for (let i = 0; i < ihm_cross_link_restraint._rowCount; ++i) { + add(i, p1) + add(i, p2) + } + + const crossLinkRestraint = { + getIndicesByElement: (element: Element, kind: Unit.Kind) => { + const map = getMapByKind(kind) + const idx = map.get(element) + return idx !== undefined ? idx : emptyIndexArray + }, + data: ihm_cross_link_restraint + } + model._staticPropertyData[PropName] = crossLinkRestraint + return crossLinkRestraint + } +} \ No newline at end of file diff --git a/src/mol-model/structure/model/formats/mmcif/pair-restraints/predicted-contacts.ts b/src/mol-model/structure/model/formats/mmcif/pair-restraints/predicted-contacts.ts new file mode 100644 index 0000000000000000000000000000000000000000..d736eabdf2c073838585736ba735813d76143d75 --- /dev/null +++ b/src/mol-model/structure/model/formats/mmcif/pair-restraints/predicted-contacts.ts @@ -0,0 +1,26 @@ +/** + * Copyright (c) 2018 Mol* contributors, licensed under MIT, See LICENSE file for more info. + * + * @author Alexander Rose <alexander.rose@weirdbyte.de> + */ + +// TODO +// ihm_predicted_contact_restraint: { +// id: int, +// entity_id_1: str, +// entity_id_2: str, +// asym_id_1: str, +// asym_id_2: str, +// comp_id_1: str, +// comp_id_2: str, +// seq_id_1: int, +// seq_id_2: int, +// atom_id_1: str, +// atom_id_2: str, +// distance_upper_limit: float, +// probability: float, +// restraint_type: Aliased<'lower bound' | 'upper bound' | 'lower and upper bound'>(str), +// model_granularity: Aliased<'by-residue' | 'by-feature' | 'by-atom'>(str), +// dataset_list_id: int, +// software_id: int, +// }, diff --git a/src/mol-view/stage.ts b/src/mol-view/stage.ts index 337cfba32ac4c327fd5af0b89cb100efe607d58e..964b42c5c51487265fd9ea392c8d26215a24e3a7 100644 --- a/src/mol-view/stage.ts +++ b/src/mol-view/stage.ts @@ -43,14 +43,14 @@ export class Stage { // this.loadPdbid('1jj2') // this.loadPdbid('4umt') // ligand has bond with order 3 - // this.loadPdbid('1crn') // small + this.loadPdbid('1crn') // small // this.loadPdbid('1rb8') // virus // this.loadPdbid('1blu') // metal coordination // this.loadPdbid('3pqr') // inter unit bonds // this.loadPdbid('4v5a') // ribosome // this.loadMmcifUrl(`../../examples/1cbs_full.bcif`) - this.loadMmcifUrl(`../../../test/pdb-dev/PDBDEV_00000001.cif`) + // this.loadMmcifUrl(`../../../test/pdb-dev/PDBDEV_00000001.cif`) } async loadMmcifUrl (url: string) { @@ -59,7 +59,7 @@ export class Stage { const structureEntity = await ModelToStructure.apply(this.ctx, modelEntity) StructureToSpacefill.apply(this.ctx, structureEntity, { ...spacefillProps, visible: true }) - // StructureToBallAndStick.apply(this.ctx, structureEntity, ballAndStickProps) + StructureToBallAndStick.apply(this.ctx, structureEntity, ballAndStickProps) StructureToDistanceRestraint.apply(this.ctx, structureEntity, ballAndStickProps) this.globalContext.components.sequenceView.setState({ structure: structureEntity.value });