Kaynağa Gözat

moved cross-link-restraint to props

Alexander Rose 5 yıl önce
ebeveyn
işleme
293b464d9f

+ 4 - 0
src/mol-model-formats/structure/common/property.ts

@@ -14,6 +14,10 @@ class FormatRegistry<T> {
         this.map.set(kind, obtain)
     }
 
+    remove(kind: ModelFormat['kind']) {
+        this.map.delete(kind)
+    }
+
     get(kind: ModelFormat['kind']) {
         return this.map.get(kind)
     }

+ 0 - 9
src/mol-model-formats/structure/mmcif.ts

@@ -17,7 +17,6 @@ import { Table } from '../../mol-data/db';
 import { AtomSiteAnisotrop } from './property/anisotropic';
 import { ComponentBond } from './property/bonds/comp';
 import { StructConn } from './property/bonds/struct_conn';
-import { ModelCrossLinkRestraint } from './property/pair-restraints/cross-links';
 
 function modelSymmetryFromMmcif(model: Model) {
     if (!MmcifFormat.is(model.sourceData)) return;
@@ -65,14 +64,6 @@ function structConnFromMmcif(model: Model) {
 }
 StructConn.Provider.formatRegistry.add('mmCIF', structConnFromMmcif)
 
-function crossLinkRestraintFromMmcif(model: Model) {
-    if (!MmcifFormat.is(model.sourceData)) return;
-    const { ihm_cross_link_restraint } = model.sourceData.data.db;
-    if (ihm_cross_link_restraint._rowCount === 0) return;
-    return ModelCrossLinkRestraint.fromTable(ihm_cross_link_restraint, model)
-}
-ModelCrossLinkRestraint.Provider.formatRegistry.add('mmCIF', crossLinkRestraintFromMmcif)
-
 //
 
 export { MmcifFormat }

+ 0 - 26
src/mol-model-formats/structure/property/pair-restraints/predicted-contacts.ts

@@ -1,26 +0,0 @@
-/**
- * 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,
-// },

+ 22 - 16
src/mol-theme/color/cross-link.ts → src/mol-model-props/integrative/cross-link-restraint/color.ts

@@ -1,23 +1,25 @@
 /**
- * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * Copyright (c) 2018-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
 
-import { Bond } from '../../mol-model/structure';
-import { Color, ColorScale } from '../../mol-util/color';
-import { Location } from '../../mol-model/location';
-import { ColorTheme, LocationColor } from '../color';
-import { Vec3 } from '../../mol-math/linear-algebra';
-import { ParamDefinition as PD } from '../../mol-util/param-definition'
-import { ThemeDataContext } from '../../mol-theme/theme';
-import { ColorListName, ColorListOptionsScale } from '../../mol-util/color/lists';
+import { Bond } from '../../../mol-model/structure';
+import { Color, ColorScale } from '../../../mol-util/color';
+import { Location } from '../../../mol-model/location';
+import { Vec3 } from '../../../mol-math/linear-algebra';
+import { ParamDefinition as PD } from '../../../mol-util/param-definition'
+import { ThemeDataContext } from '../../../mol-theme/theme';
+import { ColorListName, ColorListOptionsScale } from '../../../mol-util/color/lists';
+import { ColorTheme, LocationColor } from '../../../mol-theme/color';
+import { CustomProperty } from '../../common/custom-property';
+import { CrossLinkRestraintProvider, CrossLinkRestraint } from './property';
 
 const DefaultColor = Color(0xCCCCCC)
-const Description = 'Colors cross-links by the deviation of the observed distance versus the modeled distance (e.g. `ihm_cross_link_restraint.distance_threshold`).'
+const Description = 'Colors cross-links by the deviation of the observed distance versus the modeled distance (e.g. modeled / `ihm_cross_link_restraint.distance_threshold`).'
 
 export const CrossLinkColorThemeParams = {
-    domain: PD.Interval([-10, 10]),
+    domain: PD.Interval([0.5, 2], { step: 0.01 }),
     list: PD.ColorList<ColorListName>('red-grey', ColorListOptionsScale),
 }
 export type CrossLinkColorThemeParams = typeof CrossLinkColorThemeParams
@@ -36,8 +38,9 @@ export function CrossLinkColorTheme(ctx: ThemeDataContext, props: PD.Values<Cros
     let color: LocationColor
     let scale: ColorScale | undefined = undefined
 
-    if (ctx.structure) {
-        const crosslinks = ctx.structure.crossLinkRestraints
+    const crossLinkRestraints = ctx.structure && CrossLinkRestraintProvider.get(ctx.structure).value
+
+    if (crossLinkRestraints) {
         scale = ColorScale.create({
             domain: props.domain,
             listOrName: props.list
@@ -46,9 +49,9 @@ export function CrossLinkColorTheme(ctx: ThemeDataContext, props: PD.Values<Cros
 
         color = (location: Location): Color => {
             if (Bond.isLocation(location)) {
-                const pairs = crosslinks.getPairs(location.aIndex, location.aUnit, location.bIndex, location.bUnit)
+                const pairs = crossLinkRestraints.getPairs(location.aIndex, location.aUnit, location.bIndex, location.bUnit)
                 if (pairs) {
-                    return scaleColor(linkDistance(location) - pairs[0].distanceThreshold)
+                    return scaleColor(linkDistance(location) / pairs[0].distanceThreshold)
                 }
             }
             return DefaultColor
@@ -72,5 +75,8 @@ export const CrossLinkColorThemeProvider: ColorTheme.Provider<CrossLinkColorThem
     factory: CrossLinkColorTheme,
     getParams: getCrossLinkColorThemeParams,
     defaultValues: PD.getDefaultValues(CrossLinkColorThemeParams),
-    isApplicable: (ctx: ThemeDataContext) => !!ctx.structure && ctx.structure.crossLinkRestraints.count > 0
+    isApplicable: (ctx: ThemeDataContext) => !!ctx.structure && CrossLinkRestraint.isApplicable(ctx.structure),
+    ensureCustomProperties: (ctx: CustomProperty.Context, data: ThemeDataContext) => {
+        return data.structure ? CrossLinkRestraintProvider.attach(ctx, data.structure) : Promise.resolve()
+    }
 }

+ 6 - 6
src/mol-model-formats/structure/property/pair-restraints/cross-links.ts → src/mol-model-props/integrative/cross-link-restraint/format.ts

@@ -4,12 +4,12 @@
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
 
-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 '../../common/property';
+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 }
 

+ 47 - 9
src/mol-model/structure/structure/unit/pair-restraints/extract-cross-links.ts → src/mol-model-props/integrative/cross-link-restraint/property.ts

@@ -1,14 +1,54 @@
 /**
- * Copyright (c) 2018-2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * Copyright (c) 2018-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
 
-import Unit from '../../unit';
-import Structure from '../../structure';
-import { PairRestraints, CrossLinkRestraint } from './data';
-import { StructureElement } from '../../../structure';
-import { ModelCrossLinkRestraint } from '../../../../../mol-model-formats/structure/property/pair-restraints/cross-links';
+import { ModelCrossLinkRestraint } from './format';
+import { Unit, StructureElement, Structure, CustomPropertyDescriptor} from '../../../mol-model/structure';
+import { PairRestraints, PairRestraint } from '../pair-restraints';
+import { CustomStructureProperty } from '../../common/custom-structure-property';
+import { CustomProperty } from '../../common/custom-property';
+
+export type CrossLinkRestraintValue = PairRestraints<CrossLinkRestraint>
+
+export const CrossLinkRestraintProvider: CustomStructureProperty.Provider<{}, CrossLinkRestraintValue> = CustomStructureProperty.createProvider({
+    label: 'Cross Link Restraint',
+    descriptor: CustomPropertyDescriptor({
+        name: 'integrative-cross-link-restraint',
+        // TODO `cifExport` and `symbol`
+    }),
+    type: 'local',
+    defaultParams: {},
+    getParams: (data: Structure) => ({}),
+    isApplicable: (data: Structure) => data.models.some(m => !!ModelCrossLinkRestraint.Provider.get(m)),
+    obtain: async (ctx: CustomProperty.Context, data: Structure, props: Partial<{}>) => {
+        return extractCrossLinkRestraints(data)
+    }
+})
+
+export { CrossLinkRestraint }
+
+interface CrossLinkRestraint extends PairRestraint {
+    readonly restraintType: 'harmonic' | 'upper bound' | 'lower bound'
+    readonly distanceThreshold: number
+    readonly psi: number
+    readonly sigma1: number
+    readonly sigma2: number
+}
+
+namespace CrossLinkRestraint {
+    export enum Tag {
+        CrossLinkRestraint = 'cross-link-restraint'
+    }
+
+    export function isApplicable(structure: Structure) {
+        return structure.models.some(m => !!ModelCrossLinkRestraint.Provider.get(m))
+    }
+}
+
+
+//
 
 function _addRestraints(map: Map<number, number>, unit: Unit, restraints: ModelCrossLinkRestraint) {
     const { elements } = unit;
@@ -106,6 +146,4 @@ function extractCrossLinkRestraints(structure: Structure): PairRestraints<CrossL
     }
 
     return new PairRestraints(pairs)
-}
-
-export { extractCrossLinkRestraints };
+}

+ 57 - 17
src/mol-repr/structure/visual/cross-link-restraint-cylinder.ts → src/mol-model-props/integrative/cross-link-restraint/representation.ts

@@ -4,23 +4,29 @@
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
 
-import { ParamDefinition as PD } from '../../../mol-util/param-definition';
-import { VisualContext } from '../../visual';
-import { Structure, StructureElement, Bond } from '../../../mol-model/structure';
+import { Representation, RepresentationContext, RepresentationParamsGetter } from '../../../mol-repr/representation';
+import { ThemeRegistryContext } from '../../../mol-theme/theme';
 import { Theme } from '../../../mol-theme/theme';
 import { Mesh } from '../../../mol-geo/geometry/mesh/mesh';
 import { Vec3 } from '../../../mol-math/linear-algebra';
-import { createLinkCylinderMesh, LinkCylinderParams } from './util/link';
-import { ComplexMeshParams, ComplexVisual, ComplexMeshVisual } from '../complex-visual';
-import { VisualUpdateState } from '../../util';
 import { LocationIterator } from '../../../mol-geo/util/location-iterator';
 import { PickingId } from '../../../mol-geo/geometry/picking';
 import { EmptyLoci, Loci } from '../../../mol-model/loci';
 import { Interval } from '../../../mol-data/int';
+import { ParamDefinition as PD } from '../../../mol-util/param-definition';
+import { Structure, StructureElement, Bond } from '../../../mol-model/structure';
+import { VisualContext } from '../../../mol-repr/visual';
+import { createLinkCylinderMesh, LinkCylinderParams } from '../../../mol-repr/structure/visual/util/link';
+import { ComplexMeshParams, ComplexVisual, ComplexMeshVisual } from '../../../mol-repr/structure/complex-visual';
+import { VisualUpdateState } from '../../../mol-repr/util';
+import { ComplexRepresentation, StructureRepresentation, StructureRepresentationStateBuilder, StructureRepresentationProvider } from '../../../mol-repr/structure/representation';
+import { UnitKind, UnitKindOptions } from '../../../mol-repr/structure/visual/util/common';
+import { CustomProperty } from '../../common/custom-property';
+import { CrossLinkRestraintProvider, CrossLinkRestraint } from './property';
 
-function createCrossLinkRestraintCylinderMesh(ctx: VisualContext, structure: Structure, theme: Theme, props: PD.Values<CrossLinkRestraintParams>, mesh?: Mesh) {
+function createCrossLinkRestraintCylinderMesh(ctx: VisualContext, structure: Structure, theme: Theme, props: PD.Values<CrossLinkRestraintCylinderParams>, mesh?: Mesh) {
 
-    const crossLinks = structure.crossLinkRestraints
+    const crossLinks = CrossLinkRestraintProvider.get(structure).value!
     if (!crossLinks.count) return Mesh.createEmpty(mesh)
     const { sizeFactor } = props
 
@@ -45,21 +51,21 @@ function createCrossLinkRestraintCylinderMesh(ctx: VisualContext, structure: Str
     return createLinkCylinderMesh(ctx, builderProps, props, mesh)
 }
 
-export const CrossLinkRestraintParams = {
+export const CrossLinkRestraintCylinderParams = {
     ...ComplexMeshParams,
     ...LinkCylinderParams,
     sizeFactor: PD.Numeric(1, { min: 0, max: 10, step: 0.1 }),
 }
-export type CrossLinkRestraintParams = typeof CrossLinkRestraintParams
+export type CrossLinkRestraintCylinderParams = typeof CrossLinkRestraintCylinderParams
 
-export function CrossLinkRestraintVisual(materialId: number): ComplexVisual<CrossLinkRestraintParams> {
-    return ComplexMeshVisual<CrossLinkRestraintParams>({
-        defaultProps: PD.getDefaultValues(CrossLinkRestraintParams),
+export function CrossLinkRestraintVisual(materialId: number): ComplexVisual<CrossLinkRestraintCylinderParams> {
+    return ComplexMeshVisual<CrossLinkRestraintCylinderParams>({
+        defaultProps: PD.getDefaultValues(CrossLinkRestraintCylinderParams),
         createGeometry: createCrossLinkRestraintCylinderMesh,
         createLocationIterator: CrossLinkRestraintIterator,
         getLoci: getLinkLoci,
         eachLocation: eachCrossLink,
-        setUpdateState: (state: VisualUpdateState, newProps: PD.Values<CrossLinkRestraintParams>, currentProps: PD.Values<CrossLinkRestraintParams>) => {
+        setUpdateState: (state: VisualUpdateState, newProps: PD.Values<CrossLinkRestraintCylinderParams>, currentProps: PD.Values<CrossLinkRestraintCylinderParams>) => {
             state.createGeometry = (
                 newProps.sizeFactor !== currentProps.sizeFactor ||
                 newProps.radialSegments !== currentProps.radialSegments ||
@@ -70,7 +76,7 @@ export function CrossLinkRestraintVisual(materialId: number): ComplexVisual<Cros
 }
 
 function CrossLinkRestraintIterator(structure: Structure): LocationIterator {
-    const { pairs } = structure.crossLinkRestraints
+    const { pairs } = CrossLinkRestraintProvider.get(structure).value!
     const groupCount = pairs.length
     const instanceCount = 1
     const location = Bond.Location()
@@ -90,7 +96,7 @@ function CrossLinkRestraintIterator(structure: Structure): LocationIterator {
 function getLinkLoci(pickingId: PickingId, structure: Structure, id: number) {
     const { objectId, groupId } = pickingId
     if (id === objectId) {
-        const pair = structure.crossLinkRestraints.pairs[groupId]
+        const pair = CrossLinkRestraintProvider.get(structure).value!.pairs[groupId]
         if (pair) {
             return Bond.Loci(structure, [
                 Bond.Location(structure, pair.unitA, pair.indexA, structure, pair.unitB, pair.indexB),
@@ -102,7 +108,7 @@ function getLinkLoci(pickingId: PickingId, structure: Structure, id: number) {
 }
 
 function eachCrossLink(loci: Loci, structure: Structure, apply: (interval: Interval) => boolean) {
-    const crossLinks = structure.crossLinkRestraints
+    const crossLinks = CrossLinkRestraintProvider.get(structure).value!
     let changed = false
     if (Bond.isLoci(loci)) {
         if (!Structure.areEquivalent(loci.structure, structure)) return false
@@ -116,4 +122,38 @@ function eachCrossLink(loci: Loci, structure: Structure, apply: (interval: Inter
         }
     }
     return changed
+}
+
+//
+
+const CrossLinkRestraintVisuals = {
+    'cross-link-restraint': (ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, CrossLinkRestraintCylinderParams>) => ComplexRepresentation('Cross-link restraint', ctx, getParams, CrossLinkRestraintVisual),
+}
+
+export const CrossLinkRestraintParams = {
+    ...CrossLinkRestraintCylinderParams,
+    unitKinds: PD.MultiSelect<UnitKind>(['atomic', 'spheres'], UnitKindOptions),
+}
+export type CrossLinkRestraintParams = typeof CrossLinkRestraintParams
+export function getCrossLinkRestraintParams(ctx: ThemeRegistryContext, structure: Structure) {
+    return PD.clone(CrossLinkRestraintParams)
+}
+
+export type CrossLinkRestraintRepresentation = StructureRepresentation<CrossLinkRestraintParams>
+export function CrossLinkRestraintRepresentation(ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, CrossLinkRestraintParams>): CrossLinkRestraintRepresentation {
+    return Representation.createMulti('CrossLinkRestraint', ctx, getParams, StructureRepresentationStateBuilder, CrossLinkRestraintVisuals as unknown as Representation.Def<Structure, CrossLinkRestraintParams>)
+}
+
+export const CrossLinkRestraintRepresentationProvider: StructureRepresentationProvider<CrossLinkRestraintParams> = {
+    label: 'Cross Link Restraint',
+    description: 'Displays cross-link restraints.',
+    factory: CrossLinkRestraintRepresentation,
+    getParams: getCrossLinkRestraintParams,
+    defaultValues: PD.getDefaultValues(CrossLinkRestraintParams),
+    defaultColorTheme: { name: CrossLinkRestraint.Tag.CrossLinkRestraint },
+    defaultSizeTheme: { name: 'uniform' },
+    isApplicable: (structure: Structure) => CrossLinkRestraint.isApplicable(structure),
+    ensureCustomProperties: (ctx: CustomProperty.Context, structure: Structure) => {
+        return CrossLinkRestraintProvider.attach(ctx, structure)
+    }
 }

+ 3 - 30
src/mol-model/structure/structure/unit/pair-restraints/data.ts → src/mol-model-props/integrative/pair-restraints.ts

@@ -1,15 +1,14 @@
 /**
- * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * Copyright (c) 2018-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
 
-import Unit from '../../unit';
-import { StructureElement } from '../../../structure';
+import { StructureElement, Unit } from '../../mol-model/structure';
 
 const emptyArray: number[] = []
 
-interface PairRestraint {
+export interface PairRestraint {
     readonly unitA: Unit,
     readonly unitB: Unit,
     readonly indexA: StructureElement.UnitIndex,
@@ -48,30 +47,4 @@ export class PairRestraints<T extends PairRestraint> {
         this.count = pairs.length
         this.pairKeyIndices = pairKeyIndices
     }
-}
-
-export interface CrossLinkRestraint extends PairRestraint {
-    readonly restraintType: 'harmonic' | 'upper bound' | 'lower bound'
-    readonly distanceThreshold: number
-    readonly psi: number
-    readonly sigma1: number
-    readonly sigma2: number
-}
-
-export interface PredictedContactRestraint extends PairRestraint {
-    readonly distance_lower_limit: number
-    readonly distance_upper_limit: number
-    readonly probability: number
-    readonly restraint_type: 'lower bound' | 'upper bound' | 'lower and upper bound'
-    readonly model_granularity: 'by-residue' | 'by-feature' | 'by-atom'
-}
-
-export interface DistanceRestraint extends PairRestraint {
-    readonly upper_limit: number
-    readonly upper_limit_esd: number
-    readonly lower_limit: number
-    readonly lower_limit_esd: number
-    readonly probability: number
-    readonly restraint_type: 'lower bound' | 'upper bound' | 'lower and upper bound'
-    readonly granularity: 'by-residue' | 'by-atom'
 }

+ 1 - 9
src/mol-model/structure/structure/structure.ts

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2017-2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * Copyright (c) 2017-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
  * @author David Sehnal <david.sehnal@gmail.com>
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
@@ -16,7 +16,6 @@ import { StructureLookup3D } from './util/lookup3d';
 import { CoarseElements } from '../model/properties/coarse';
 import { StructureSubsetBuilder } from './util/subset-builder';
 import { InterUnitBonds, computeInterUnitBonds, Bond } from './unit/bonds';
-import { PairRestraints, CrossLinkRestraint, extractCrossLinkRestraints } from './unit/pair-restraints';
 import StructureSymmetry from './symmetry';
 import StructureProperties from './properties';
 import { ResidueIndex, ChainIndex, EntityIndex } from '../model/indexing';
@@ -41,7 +40,6 @@ class Structure {
         parent?: Structure,
         lookup3d?: StructureLookup3D,
         interUnitBonds?: InterUnitBonds,
-        crossLinkRestraints?: PairRestraints<CrossLinkRestraint>,
         unitSymmetryGroups?: ReadonlyArray<Unit.SymmetryGroup>,
         unitSymmetryGroupsIndexMap?: IntMap<number>,
         carbohydrates?: Carbohydrates,
@@ -228,12 +226,6 @@ class Structure {
         return this._props.interUnitBonds;
     }
 
-    get crossLinkRestraints() {
-        if (this._props.crossLinkRestraints) return this._props.crossLinkRestraints;
-        this._props.crossLinkRestraints = extractCrossLinkRestraints(this);
-        return this._props.crossLinkRestraints;
-    }
-
     get unitSymmetryGroups(): ReadonlyArray<Unit.SymmetryGroup> {
         if (this._props.unitSymmetryGroups) return this._props.unitSymmetryGroups;
         this._props.unitSymmetryGroups = StructureSymmetry.computeTransformGroups(this);

+ 0 - 10
src/mol-model/structure/structure/unit/pair-restraints.ts

@@ -1,10 +0,0 @@
-/**
- * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author Alexander Rose <alexander.rose@weirdbyte.de>
- */
-
-export * from './pair-restraints/data'
-export * from './pair-restraints/extract-cross-links'
-// export * from './pair-restraints/extract-predicted-contacts'
-// export * from './pair-restraints/extract-distance-restraints'

+ 0 - 7
src/mol-model/structure/structure/unit/pair-restraints/extract-distance-restraints.ts

@@ -1,7 +0,0 @@
-/**
- * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author Alexander Rose <alexander.rose@weirdbyte.de>
- */
-
-// TODO extract from `_ma_distance_restraints`

+ 0 - 7
src/mol-model/structure/structure/unit/pair-restraints/extract-predicted-contacts.ts

@@ -1,7 +0,0 @@
-/**
- * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author Alexander Rose <alexander.rose@weirdbyte.de>
- */
-
-// TODO extract from `ihm_predicted_contact_restraint`

+ 2 - 0
src/mol-plugin/behavior/dynamic/custom-props.ts

@@ -10,6 +10,8 @@ export { Interactions } from './custom-props/computed/interactions'
 export { SecondaryStructure } from './custom-props/computed/secondary-structure'
 export { ValenceModel } from './custom-props/computed/valence-model'
 
+export { CrossLinkRestraint } from './custom-props/integrative/cross-link-restraint'
+
 export { PDBeStructureQualityReport } from './custom-props/pdbe/structure-quality-report'
 export { RCSBAssemblySymmetry } from './custom-props/rcsb/assembly-symmetry'
 export { RCSBValidationReport } from './custom-props/rcsb/validation-report'

+ 45 - 0
src/mol-plugin/behavior/dynamic/custom-props/integrative/cross-link-restraint.ts

@@ -0,0 +1,45 @@
+/**
+ * Copyright (c) 2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
+import { PluginBehavior } from '../../../behavior';
+import { ModelCrossLinkRestraint } from '../../../../../mol-model-props/integrative/cross-link-restraint/format';
+import { Model } from '../../../../../mol-model/structure';
+import { MmcifFormat } from '../../../../../mol-model-formats/structure/mmcif';
+import { CrossLinkRestraintRepresentationProvider } from '../../../../../mol-model-props/integrative/cross-link-restraint/representation';
+import { CrossLinkColorThemeProvider } from '../../../../../mol-model-props/integrative/cross-link-restraint/color';
+import { CrossLinkRestraint as _CrossLinkRestraint } from '../../../../../mol-model-props/integrative/cross-link-restraint/property';
+
+const Tag = _CrossLinkRestraint.Tag
+
+export const CrossLinkRestraint = PluginBehavior.create<{ }>({
+    name: 'integrative-cross-link-restraint',
+    category: 'custom-props',
+    display: { name: 'Cross Link Restraint' },
+    ctor: class extends PluginBehavior.Handler<{ }> {
+        private provider = ModelCrossLinkRestraint.Provider
+
+        register(): void {
+            this.provider.formatRegistry.add('mmCIF', crossLinkRestraintFromMmcif)
+
+            this.ctx.structureRepresentation.themeCtx.colorThemeRegistry.add(Tag.CrossLinkRestraint, CrossLinkColorThemeProvider)
+            this.ctx.structureRepresentation.registry.add(Tag.CrossLinkRestraint, CrossLinkRestraintRepresentationProvider)
+        }
+
+        unregister() {
+            this.provider.formatRegistry.remove('mmCIF')
+
+            this.ctx.structureRepresentation.themeCtx.colorThemeRegistry.remove(Tag.CrossLinkRestraint)
+            this.ctx.structureRepresentation.registry.remove(Tag.CrossLinkRestraint)
+        }
+    }
+});
+
+function crossLinkRestraintFromMmcif(model: Model) {
+    if (!MmcifFormat.is(model.sourceData)) return;
+    const { ihm_cross_link_restraint } = model.sourceData.data.db;
+    if (ihm_cross_link_restraint._rowCount === 0) return;
+    return ModelCrossLinkRestraint.fromTable(ihm_cross_link_restraint, model)
+}

+ 4 - 1
src/mol-plugin/index.ts

@@ -70,14 +70,17 @@ export const DefaultPluginSpec: PluginSpec = {
         PluginSpec.Behavior(PluginBehaviors.Representation.SelectLoci),
         PluginSpec.Behavior(PluginBehaviors.Representation.DefaultLociLabelProvider),
         PluginSpec.Behavior(PluginBehaviors.Camera.FocusLoci),
+        PluginSpec.Behavior(StructureRepresentationInteraction),
+
         PluginSpec.Behavior(PluginBehaviors.CustomProps.AccessibleSurfaceArea),
         PluginSpec.Behavior(PluginBehaviors.CustomProps.Interactions),
         PluginSpec.Behavior(PluginBehaviors.CustomProps.SecondaryStructure),
         PluginSpec.Behavior(PluginBehaviors.CustomProps.ValenceModel),
+        PluginSpec.Behavior(PluginBehaviors.CustomProps.CrossLinkRestraint),
+
         PluginSpec.Behavior(PluginBehaviors.CustomProps.PDBeStructureQualityReport, { autoAttach: true, showTooltip: true }),
         PluginSpec.Behavior(PluginBehaviors.CustomProps.RCSBAssemblySymmetry),
         PluginSpec.Behavior(PluginBehaviors.CustomProps.RCSBValidationReport),
-        PluginSpec.Behavior(StructureRepresentationInteraction)
     ],
     customParamEditors: [
         [CreateVolumeStreamingBehavior, VolumeStreamingCustomControls]

+ 0 - 2
src/mol-repr/structure/registry.ts

@@ -11,7 +11,6 @@ import { BallAndStickRepresentationProvider } from './representation/ball-and-st
 import { GaussianSurfaceRepresentationProvider } from './representation/gaussian-surface';
 import { CarbohydrateRepresentationProvider } from './representation/carbohydrate';
 import { SpacefillRepresentationProvider } from './representation/spacefill';
-import { DistanceRestraintRepresentationProvider } from './representation/distance-restraint';
 import { PointRepresentationProvider } from './representation/point';
 import { StructureRepresentationState } from './representation';
 import { PuttyRepresentationProvider } from './representation/putty';
@@ -34,7 +33,6 @@ export const BuiltInStructureRepresentations = {
     'cartoon': CartoonRepresentationProvider,
     'ball-and-stick': BallAndStickRepresentationProvider,
     'carbohydrate': CarbohydrateRepresentationProvider,
-    'distance-restraint': DistanceRestraintRepresentationProvider,
     'ellipsoid': EllipsoidRepresentationProvider,
     'gaussian-surface': GaussianSurfaceRepresentationProvider,
     // 'gaussian-volume': GaussianVolumeRepresentationProvider, // TODO disabled for now, needs more work

+ 0 - 43
src/mol-repr/structure/representation/distance-restraint.ts

@@ -1,43 +0,0 @@
-/**
- * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author Alexander Rose <alexander.rose@weirdbyte.de>
- */
-
-import { CrossLinkRestraintVisual, CrossLinkRestraintParams } from '../visual/cross-link-restraint-cylinder';
-import { ParamDefinition as PD } from '../../../mol-util/param-definition';
-import { ComplexRepresentation } from '../complex-representation';
-import { StructureRepresentation, StructureRepresentationProvider, StructureRepresentationStateBuilder } from '../representation';
-import { Representation, RepresentationContext, RepresentationParamsGetter } from '../../../mol-repr/representation';
-import { ThemeRegistryContext } from '../../../mol-theme/theme';
-import { Structure } from '../../../mol-model/structure';
-import { UnitKind, UnitKindOptions } from '../visual/util/common';
-
-const DistanceRestraintVisuals = {
-    'distance-restraint': (ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, CrossLinkRestraintParams>) => ComplexRepresentation('Cross-link restraint', ctx, getParams, CrossLinkRestraintVisual),
-}
-
-export const DistanceRestraintParams = {
-    ...CrossLinkRestraintParams,
-    unitKinds: PD.MultiSelect<UnitKind>(['atomic', 'spheres'], UnitKindOptions),
-}
-export type DistanceRestraintParams = typeof DistanceRestraintParams
-export function getDistanceRestraintParams(ctx: ThemeRegistryContext, structure: Structure) {
-    return PD.clone(DistanceRestraintParams)
-}
-
-export type DistanceRestraintRepresentation = StructureRepresentation<DistanceRestraintParams>
-export function DistanceRestraintRepresentation(ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, DistanceRestraintParams>): DistanceRestraintRepresentation {
-    return Representation.createMulti('DistanceRestraint', ctx, getParams, StructureRepresentationStateBuilder, DistanceRestraintVisuals as unknown as Representation.Def<Structure, DistanceRestraintParams>)
-}
-
-export const DistanceRestraintRepresentationProvider: StructureRepresentationProvider<DistanceRestraintParams> = {
-    label: 'Distance Restraint',
-    description: 'Displays cross-link distance restraints.',
-    factory: DistanceRestraintRepresentation,
-    getParams: getDistanceRestraintParams,
-    defaultValues: PD.getDefaultValues(DistanceRestraintParams),
-    defaultColorTheme: { name: 'cross-link' },
-    defaultSizeTheme: { name: 'uniform' },
-    isApplicable: (structure: Structure) => structure.crossLinkRestraints.count > 0
-}

+ 0 - 2
src/mol-theme/color.ts

@@ -13,7 +13,6 @@ import { deepEqual } from '../mol-util';
 import { ParamDefinition as PD } from '../mol-util/param-definition';
 import { ThemeDataContext, ThemeRegistry, ThemeProvider } from './theme';
 import { ChainIdColorThemeProvider } from './color/chain-id';
-import { CrossLinkColorThemeProvider } from './color/cross-link';
 import { ElementIndexColorThemeProvider } from './color/element-index';
 import { ElementSymbolColorThemeProvider } from './color/element-symbol';
 import { MoleculeTypeColorThemeProvider } from './color/molecule-type';
@@ -76,7 +75,6 @@ namespace ColorTheme {
 export const BuiltInColorThemes = {
     'carbohydrate-symbol': CarbohydrateSymbolColorThemeProvider,
     'chain-id': ChainIdColorThemeProvider,
-    'cross-link': CrossLinkColorThemeProvider,
     'element-index': ElementIndexColorThemeProvider,
     'element-symbol': ElementSymbolColorThemeProvider,
     'entity-source': EntitySourceColorThemeProvider,