/** * Copyright (c) 2019-2020 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author Alexander Rose */ import { Structure } from '../../mol-model/structure'; import { DSSPComputationParams, DSSPComputationProps, computeUnitDSSP } from './secondary-structure/dssp'; import { SecondaryStructure } from '../../mol-model/structure/model/properties/seconday-structure'; import { ParamDefinition as PD } from '../../mol-util/param-definition'; import { Unit } from '../../mol-model/structure/structure'; import { CustomStructureProperty } from '../common/custom-structure-property'; import { CustomProperty } from '../common/custom-property'; import { ModelSecondaryStructure } from '../../mol-model-formats/structure/property/secondary-structure'; import { MmcifFormat } from '../../mol-model-formats/structure/mmcif'; import { CustomPropertyDescriptor } from '../../mol-model/structure/common/custom-property'; function getSecondaryStructureParams(data?: Structure) { let defaultType = 'model' as 'model' | 'dssp' if (data) { defaultType = 'dssp' for (let i = 0, il = data.models.length; i < il; ++i) { const m = data.models[i] if (MmcifFormat.is(m.sourceData)) { if (m.sourceData.data.db.struct_conf.id.isDefined || m.sourceData.data.db.struct_sheet_range.id.isDefined || m.sourceData.data.db.database_2.database_id.isDefined ) { // if there is any secondary structure definition given or if there is // an archival model, don't calculate dssp by default defaultType = 'model' break } } } } return { type: PD.MappedStatic(defaultType, { 'model': PD.EmptyGroup({ label: 'Model' }), 'dssp': PD.Group(DSSPComputationParams, { label: 'DSSP', isFlat: true }) }, { options: [['model', 'Model'], ['dssp', 'DSSP']] }) } } export const SecondaryStructureParams = getSecondaryStructureParams() export type SecondaryStructureParams = typeof SecondaryStructureParams export type SecondaryStructureProps = PD.Values /** Maps `unit.id` to `SecondaryStructure` */ export type SecondaryStructureValue = Map export const SecondaryStructureProvider: CustomStructureProperty.Provider = CustomStructureProperty.createProvider({ label: 'Secondary Structure', descriptor: CustomPropertyDescriptor({ name: 'molstar_computed_secondary_structure', // TODO `cifExport` and `symbol` }), type: 'root', defaultParams: SecondaryStructureParams, getParams: getSecondaryStructureParams, isApplicable: (data: Structure) => true, obtain: async (ctx: CustomProperty.Context, data: Structure, props: Partial) => { const p = { ...PD.getDefaultValues(SecondaryStructureParams), ...props } switch (p.type.name) { case 'dssp': return await computeDssp(data, p.type.params) case 'model': return await computeModel(data) } } }) async function computeDssp(structure: Structure, props: DSSPComputationProps): Promise { // TODO take inter-unit hbonds into account for bridge, ladder, sheet assignment // TODO use Zhang-Skolnik for CA alpha only parts or for coarse parts with per-residue elements const map = new Map() for (let i = 0, il = structure.unitSymmetryGroups.length; i < il; ++i) { const u = structure.unitSymmetryGroups[i].units[0] if (Unit.isAtomic(u)) { const secondaryStructure = await computeUnitDSSP(u, props) map.set(u.invariantId, secondaryStructure) } } return map } async function computeModel(structure: Structure): Promise { const map = new Map() for (let i = 0, il = structure.unitSymmetryGroups.length; i < il; ++i) { const u = structure.unitSymmetryGroups[i].units[0] if (Unit.isAtomic(u)) { const secondaryStructure = ModelSecondaryStructure.Provider.get(u.model) if (secondaryStructure) { map.set(u.invariantId, secondaryStructure) } } } return map }