psf.ts 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  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 { PsfFile } from '../../mol-io/reader/psf/parser';
  7. import { Column, Table } from '../../mol-data/db';
  8. import { EntityBuilder } from './common/entity';
  9. import { ComponentBuilder } from './common/component';
  10. import { guessElementSymbolString } from './util';
  11. import { MoleculeType, getMoleculeType } from '../../mol-model/structure/model/types';
  12. import { getChainId } from './common/util';
  13. import { Task } from '../../mol-task';
  14. import { ModelFormat } from './format';
  15. import { Topology } from '../../mol-model/structure/topology/topology';
  16. import { createBasic, BasicSchema } from './basic/schema';
  17. function getBasic(atoms: PsfFile['atoms']) {
  18. const auth_atom_id = atoms.atomName
  19. const auth_comp_id = atoms.residueName
  20. const entityIds = new Array<string>(atoms.count)
  21. const asymIds = new Array<string>(atoms.count)
  22. const seqIds = new Uint32Array(atoms.count)
  23. const ids = new Uint32Array(atoms.count)
  24. const entityBuilder = new EntityBuilder()
  25. const componentBuilder = new ComponentBuilder(atoms.residueId, atoms.atomName)
  26. let currentEntityId = ''
  27. let currentAsymIndex = 0
  28. let currentAsymId = ''
  29. let currentSeqId = 0
  30. let prevMoleculeType = MoleculeType.Unknown
  31. let prevResidueNumber = -1
  32. for (let i = 0, il = atoms.count; i < il; ++i) {
  33. const residueNumber = atoms.residueId.value(i)
  34. if (residueNumber !== prevResidueNumber) {
  35. const compId = atoms.residueName.value(i)
  36. const moleculeType = getMoleculeType(componentBuilder.add(compId, i).type, compId)
  37. if (moleculeType !== prevMoleculeType || residueNumber !== prevResidueNumber + 1) {
  38. currentAsymId = getChainId(currentAsymIndex)
  39. currentAsymIndex += 1
  40. currentSeqId = 0
  41. }
  42. currentEntityId = entityBuilder.getEntityId(compId, moleculeType, currentAsymId)
  43. currentSeqId += 1
  44. prevResidueNumber = residueNumber
  45. prevMoleculeType = moleculeType
  46. }
  47. entityIds[i] = currentEntityId
  48. asymIds[i] = currentAsymId
  49. seqIds[i] = currentSeqId
  50. ids[i] = i
  51. }
  52. const auth_asym_id = Column.ofStringArray(asymIds)
  53. const atom_site = Table.ofPartialColumns(BasicSchema.atom_site, {
  54. auth_asym_id,
  55. auth_atom_id,
  56. auth_comp_id,
  57. auth_seq_id: atoms.residueId,
  58. id: Column.ofIntArray(ids),
  59. label_asym_id: auth_asym_id,
  60. label_atom_id: auth_atom_id,
  61. label_comp_id: auth_comp_id,
  62. label_seq_id: Column.ofIntArray(seqIds),
  63. label_entity_id: Column.ofStringArray(entityIds),
  64. occupancy: Column.ofConst(1, atoms.count, Column.Schema.float),
  65. type_symbol: Column.ofStringArray(Column.mapToArray(atoms.atomName, s => guessElementSymbolString(s))),
  66. pdbx_PDB_model_num: Column.ofConst(1, atoms.count, Column.Schema.int),
  67. }, atoms.count)
  68. return createBasic({
  69. entity: entityBuilder.getEntityTable(),
  70. chem_comp: componentBuilder.getChemCompTable(),
  71. atom_site
  72. })
  73. }
  74. //
  75. export { PsfFormat }
  76. type PsfFormat = ModelFormat<PsfFile>
  77. namespace PsfFormat {
  78. export function is(x: ModelFormat): x is PsfFormat {
  79. return x.kind === 'psf'
  80. }
  81. export function fromPsf(psf: PsfFile): PsfFormat {
  82. return { kind: 'psf', name: psf.id, data: psf };
  83. }
  84. }
  85. export function topologyFromPsf(psf: PsfFile): Task<Topology> {
  86. return Task.create('Parse PSF', async ctx => {
  87. const format = PsfFormat.fromPsf(psf);
  88. const basic = getBasic(psf.atoms)
  89. const { atomIdA, atomIdB } = psf.bonds
  90. const bonds = {
  91. indexA: Column.ofLambda({
  92. value: (row: number) => atomIdA.value(row) - 1,
  93. rowCount: atomIdA.rowCount,
  94. schema: atomIdA.schema,
  95. }),
  96. indexB: Column.ofLambda({
  97. value: (row: number) => atomIdB.value(row) - 1,
  98. rowCount: atomIdB.rowCount,
  99. schema: atomIdB.schema,
  100. }),
  101. order: Column.ofConst(1, psf.bonds.count, Column.Schema.int)
  102. }
  103. return Topology.create(psf.id, basic, bonds, format)
  104. })
  105. }