|
@@ -5,60 +5,59 @@
|
|
|
*/
|
|
|
|
|
|
import { CustomPropertyDescriptor, Structure } from '../../mol-model/structure';
|
|
|
-import { Task } from '../../mol-task';
|
|
|
-import { DSSPComputationParams, computeUnitDSSP } from './secondary-structure/dssp';
|
|
|
+import { RuntimeContext } from '../../mol-task';
|
|
|
+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 { idFactory } from '../../mol-util/id-factory';
|
|
|
+import { CustomStructureProperty } from '../common/custom-property-registry';
|
|
|
|
|
|
-const nextSecondaryStructureId = idFactory()
|
|
|
+// TODO get default params based on structure
|
|
|
+// /**
|
|
|
+// * Attaches ComputedSecondaryStructure property when unavailable in sourceData and
|
|
|
+// * when not an archival file (i.e. no database_2.database_id field)
|
|
|
+// */
|
|
|
+// export async function ensureSecondaryStructure(s: Structure) {
|
|
|
+// if (s.models.length === 1 && s.model && s.model.sourceData.kind === 'mmCIF') {
|
|
|
+// if (!s.model.sourceData.data.struct_conf.id.isDefined && !s.model.sourceData.data.struct_sheet_range.id.isDefined &&
|
|
|
+// !s.model.sourceData.data.database_2.database_id.isDefined
|
|
|
+// ) {
|
|
|
+// await ComputedSecondaryStructure.attach(s)
|
|
|
+// }
|
|
|
+// }
|
|
|
+// }
|
|
|
|
|
|
-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 const SecondaryStructureParams = {
|
|
|
+ type: PD.MappedStatic('mmcif', {
|
|
|
+ 'mmcif': PD.EmptyGroup({ label: 'mmCIF' }),
|
|
|
+ 'dssp': PD.Group(DSSPComputationParams, { label: 'DSSP', isFlat: true })
|
|
|
+ }, { options: [['mmcif', 'mmCIF'], ['dssp', 'DSSP']] })
|
|
|
+}
|
|
|
+export type SecondaryStructureParams = typeof SecondaryStructureParams
|
|
|
+export type SecondaryStructureProps = PD.Values<SecondaryStructureParams>
|
|
|
|
|
|
- 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 type SecondaryStructureValue = Map<number, SecondaryStructure>
|
|
|
|
|
|
- export const Descriptor = CustomPropertyDescriptor({
|
|
|
+export const SecondaryStructureProvider: CustomStructureProperty.Provider<SecondaryStructureParams, SecondaryStructureValue> = CustomStructureProperty.createProvider({
|
|
|
+ label: 'Secondary Structure',
|
|
|
+ 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;
|
|
|
+ }),
|
|
|
+ defaultParams: SecondaryStructureParams,
|
|
|
+ getParams: (data: Structure) => SecondaryStructureParams,
|
|
|
+ isApplicable: (data: Structure) => true,
|
|
|
+ compute: async (ctx: RuntimeContext, data: Structure, props: Partial<SecondaryStructureProps>) => {
|
|
|
+ const p = { ...PD.getDefaultValues(SecondaryStructureParams), ...props }
|
|
|
+ switch (p.type.name) {
|
|
|
+ case 'dssp': return await computeDssp(data, p.type.params)
|
|
|
+ case 'mmcif': return await computeMmcif(data)
|
|
|
+ }
|
|
|
}
|
|
|
-}
|
|
|
+})
|
|
|
|
|
|
-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 }
|
|
|
+async function computeDssp(structure: Structure, props: DSSPComputationProps): Promise<SecondaryStructureValue> {
|
|
|
// 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
|
|
@@ -66,9 +65,20 @@ async function computeSecondaryStructure(structure: Structure, params: Partial<S
|
|
|
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)
|
|
|
+ const secondaryStructure = await computeUnitDSSP(u, props)
|
|
|
map.set(u.invariantId, secondaryStructure)
|
|
|
}
|
|
|
}
|
|
|
- return { id: nextSecondaryStructureId(), map }
|
|
|
+ return map
|
|
|
+}
|
|
|
+
|
|
|
+async function computeMmcif(structure: Structure): Promise<SecondaryStructureValue> {
|
|
|
+ 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)) {
|
|
|
+ map.set(u.invariantId, u.model.properties.secondaryStructure)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return map
|
|
|
}
|