/** * Copyright (c) 2019 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author Alexander Rose <alexander.rose@weirdbyte.de> */ import { CustomPropertyDescriptor, Structure } from 'mol-model/structure'; import { Task } from 'mol-task'; import { DSSPComputationParams, 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 { idFactory } from 'mol-util/id-factory'; const nextSecondaryStructureId = idFactory() export namespace ComputedSecondaryStructure { export type Property = { id: number map: Map<number, SecondaryStructure> } export function get(structure: Structure): Property | undefined { return structure.inheritedPropertyData.__ComputedSecondaryStructure__; } function set(structure: Structure, prop: Property) { (structure.inheritedPropertyData.__ComputedSecondaryStructure__ as Property) = prop; } export function createAttachTask(params: Partial<SecondaryStructureComputationProps> = {}) { return (structure: Structure) => Task.create('Compute Secondary Structure', async ctx => { if (get(structure)) return true; return await attachFromCifOrCompute(structure, params) }); } export const Descriptor = CustomPropertyDescriptor({ isStatic: true, name: 'molstar_computed_secondary_structure', // TODO `cifExport` and `symbol` }); export async function attachFromCifOrCompute(structure: Structure, params: Partial<SecondaryStructureComputationProps> = {}) { if (structure.customPropertyDescriptors.has(Descriptor)) return true; const compSecStruc = await computeSecondaryStructure(structure, params) structure.customPropertyDescriptors.add(Descriptor); set(structure, compSecStruc); return true; } } export const SecondaryStructureComputationParams = { ...DSSPComputationParams } export type SecondaryStructureComputationParams = typeof SecondaryStructureComputationParams export type SecondaryStructureComputationProps = PD.Values<SecondaryStructureComputationParams> async function computeSecondaryStructure(structure: Structure, params: Partial<SecondaryStructureComputationProps>): Promise<ComputedSecondaryStructure.Property> { const p = { ...PD.getDefaultValues(SecondaryStructureComputationParams), params } // TODO take inter-unit hbonds into account for bridge, ladder, sheet assignment // TODO store unit-only secStruc as custom unit property??? // TODO use Zhang-Skolnik for CA alpha only parts or for coarse parts with per-residue elements const map = new Map<number, SecondaryStructure>() 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, p) map.set(u.invariantId, secondaryStructure) } } return { id: nextSecondaryStructureId(), map } }