parser.ts 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. /**
  2. * Copyright (c) 2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author David Sehnal <david.sehnal@gmail.com>
  5. */
  6. import { Column } from '../../../mol-data/db';
  7. import { Task } from '../../../mol-task';
  8. import TokenColumn from '../common/text/column/token';
  9. import { TokenBuilder, Tokenizer } from '../common/text/tokenizer';
  10. import { ReaderResult as Result } from '../result';
  11. /** Subset of the MolFile V2000 format */
  12. export interface MolFile {
  13. readonly title: string,
  14. readonly program: string,
  15. readonly comment: string,
  16. readonly atoms: {
  17. readonly count: number,
  18. readonly x: Column<number>,
  19. readonly y: Column<number>,
  20. readonly z: Column<number>,
  21. readonly type_symbol: Column<string>
  22. },
  23. readonly bonds: {
  24. readonly count: number
  25. readonly atomIdxA: Column<number>,
  26. readonly atomIdxB: Column<number>,
  27. readonly order: Column<number>
  28. }
  29. }
  30. export function handleAtoms(tokenizer: Tokenizer, count: number): MolFile['atoms'] {
  31. const x = TokenBuilder.create(tokenizer.data, count * 2);
  32. const y = TokenBuilder.create(tokenizer.data, count * 2);
  33. const z = TokenBuilder.create(tokenizer.data, count * 2);
  34. const type_symbol = TokenBuilder.create(tokenizer.data, count * 2);
  35. for (let i = 0; i < count; ++i) {
  36. Tokenizer.markLine(tokenizer);
  37. const { tokenStart: s, position } = tokenizer;
  38. Tokenizer.trim(tokenizer, s, s + 10);
  39. TokenBuilder.addUnchecked(x, tokenizer.tokenStart, tokenizer.tokenEnd);
  40. Tokenizer.trim(tokenizer, s + 10, s + 20);
  41. TokenBuilder.addUnchecked(y, tokenizer.tokenStart, tokenizer.tokenEnd);
  42. Tokenizer.trim(tokenizer, s + 20, s + 30);
  43. TokenBuilder.addUnchecked(z, tokenizer.tokenStart, tokenizer.tokenEnd);
  44. Tokenizer.trim(tokenizer, s + 31, s + 34);
  45. TokenBuilder.addUnchecked(type_symbol, tokenizer.tokenStart, tokenizer.tokenEnd);
  46. tokenizer.position = position;
  47. }
  48. return {
  49. count,
  50. x: TokenColumn(x)(Column.Schema.float),
  51. y: TokenColumn(y)(Column.Schema.float),
  52. z: TokenColumn(z)(Column.Schema.float),
  53. type_symbol: TokenColumn(type_symbol)(Column.Schema.str)
  54. };
  55. }
  56. export function handleBonds(tokenizer: Tokenizer, count: number): MolFile['bonds'] {
  57. const atomIdxA = TokenBuilder.create(tokenizer.data, count * 2);
  58. const atomIdxB = TokenBuilder.create(tokenizer.data, count * 2);
  59. const order = TokenBuilder.create(tokenizer.data, count * 2);
  60. for (let i = 0; i < count; ++i) {
  61. Tokenizer.markLine(tokenizer);
  62. const { tokenStart: s, position } = tokenizer;
  63. Tokenizer.trim(tokenizer, s, s + 3);
  64. TokenBuilder.addUnchecked(atomIdxA, tokenizer.tokenStart, tokenizer.tokenEnd);
  65. Tokenizer.trim(tokenizer, s + 3, s + 6);
  66. TokenBuilder.addUnchecked(atomIdxB, tokenizer.tokenStart, tokenizer.tokenEnd);
  67. Tokenizer.trim(tokenizer, s + 6, s + 9);
  68. TokenBuilder.addUnchecked(order, tokenizer.tokenStart, tokenizer.tokenEnd);
  69. tokenizer.position = position;
  70. }
  71. return {
  72. count,
  73. atomIdxA: TokenColumn(atomIdxA)(Column.Schema.int),
  74. atomIdxB: TokenColumn(atomIdxB)(Column.Schema.int),
  75. order: TokenColumn(order)(Column.Schema.int)
  76. };
  77. }
  78. function parseInternal(data: string): Result<MolFile> {
  79. const tokenizer = Tokenizer(data);
  80. const title = Tokenizer.readLine(tokenizer).trim();
  81. const program = Tokenizer.readLine(tokenizer).trim();
  82. const comment = Tokenizer.readLine(tokenizer).trim();
  83. const counts = Tokenizer.readLine(tokenizer);
  84. const atomCount = +counts.substr(0, 3), bondCount = +counts.substr(3, 3);
  85. const atoms = handleAtoms(tokenizer, atomCount);
  86. const bonds = handleBonds(tokenizer, bondCount);
  87. const result: MolFile = {
  88. title,
  89. program,
  90. comment,
  91. atoms,
  92. bonds
  93. };
  94. return Result.success(result);
  95. }
  96. export function parseMol(data: string) {
  97. return Task.create<Result<MolFile>>('Parse Mol', async () => {
  98. return parseInternal(data);
  99. });
  100. }