secondary-structure.ts 4.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. /**
  2. * Copyright (c) 2019-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author Alexander Rose <alexander.rose@weirdbyte.de>
  5. */
  6. import { Structure } from '../../mol-model/structure';
  7. import { DSSPComputationParams, DSSPComputationProps, computeUnitDSSP } from './secondary-structure/dssp';
  8. import { SecondaryStructure } from '../../mol-model/structure/model/properties/seconday-structure';
  9. import { ParamDefinition as PD } from '../../mol-util/param-definition';
  10. import { Unit } from '../../mol-model/structure/structure';
  11. import { CustomStructureProperty } from '../common/custom-structure-property';
  12. import { CustomProperty } from '../common/custom-property';
  13. import { ModelSecondaryStructure } from '../../mol-model-formats/structure/property/secondary-structure';
  14. import { MmcifFormat } from '../../mol-model-formats/structure/mmcif';
  15. import { CustomPropertyDescriptor } from '../../mol-model/structure/common/custom-property';
  16. function getSecondaryStructureParams(data?: Structure) {
  17. let defaultType = 'model' as 'model' | 'dssp'
  18. if (data) {
  19. defaultType = 'dssp'
  20. for (let i = 0, il = data.models.length; i < il; ++i) {
  21. const m = data.models[i]
  22. if (MmcifFormat.is(m.sourceData)) {
  23. if (m.sourceData.data.db.struct_conf.id.isDefined ||
  24. m.sourceData.data.db.struct_sheet_range.id.isDefined ||
  25. m.sourceData.data.db.database_2.database_id.isDefined
  26. ) {
  27. // if there is any secondary structure definition given or if there is
  28. // an archival model, don't calculate dssp by default
  29. defaultType = 'model'
  30. break
  31. }
  32. }
  33. }
  34. }
  35. return {
  36. type: PD.MappedStatic(defaultType, {
  37. 'model': PD.EmptyGroup({ label: 'Model' }),
  38. 'dssp': PD.Group(DSSPComputationParams, { label: 'DSSP', isFlat: true })
  39. }, { options: [['model', 'Model'], ['dssp', 'DSSP']] })
  40. }
  41. }
  42. export const SecondaryStructureParams = getSecondaryStructureParams()
  43. export type SecondaryStructureParams = typeof SecondaryStructureParams
  44. export type SecondaryStructureProps = PD.Values<SecondaryStructureParams>
  45. /** Maps `unit.id` to `SecondaryStructure` */
  46. export type SecondaryStructureValue = Map<number, SecondaryStructure>
  47. export const SecondaryStructureProvider: CustomStructureProperty.Provider<SecondaryStructureParams, SecondaryStructureValue> = CustomStructureProperty.createProvider({
  48. label: 'Secondary Structure',
  49. descriptor: CustomPropertyDescriptor({
  50. name: 'molstar_computed_secondary_structure',
  51. // TODO `cifExport` and `symbol`
  52. }),
  53. type: 'root',
  54. defaultParams: SecondaryStructureParams,
  55. getParams: getSecondaryStructureParams,
  56. isApplicable: (data: Structure) => true,
  57. obtain: async (ctx: CustomProperty.Context, data: Structure, props: Partial<SecondaryStructureProps>) => {
  58. const p = { ...PD.getDefaultValues(SecondaryStructureParams), ...props }
  59. switch (p.type.name) {
  60. case 'dssp': return await computeDssp(data, p.type.params)
  61. case 'model': return await computeModel(data)
  62. }
  63. }
  64. })
  65. async function computeDssp(structure: Structure, props: DSSPComputationProps): Promise<SecondaryStructureValue> {
  66. // TODO take inter-unit hbonds into account for bridge, ladder, sheet assignment
  67. // TODO use Zhang-Skolnik for CA alpha only parts or for coarse parts with per-residue elements
  68. const map = new Map<number, SecondaryStructure>()
  69. for (let i = 0, il = structure.unitSymmetryGroups.length; i < il; ++i) {
  70. const u = structure.unitSymmetryGroups[i].units[0]
  71. if (Unit.isAtomic(u)) {
  72. const secondaryStructure = await computeUnitDSSP(u, props)
  73. map.set(u.invariantId, secondaryStructure)
  74. }
  75. }
  76. return map
  77. }
  78. async function computeModel(structure: Structure): Promise<SecondaryStructureValue> {
  79. const map = new Map<number, SecondaryStructure>()
  80. for (let i = 0, il = structure.unitSymmetryGroups.length; i < il; ++i) {
  81. const u = structure.unitSymmetryGroups[i].units[0]
  82. if (Unit.isAtomic(u)) {
  83. const secondaryStructure = ModelSecondaryStructure.Provider.get(u.model)
  84. if (secondaryStructure) {
  85. map.set(u.invariantId, secondaryStructure)
  86. }
  87. }
  88. }
  89. return map
  90. }