properties.ts 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. /**
  2. * Copyright (c) 2017-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author Alexander Rose <alexander.rose@weirdbyte.de>
  5. * @author Panagiotis Tourlas <panagiot_tourlov@hotmail.com>
  6. */
  7. import { MolScriptBuilder } from '../../../mol-script/language/builder';
  8. const B = MolScriptBuilder;
  9. import { PropertyDict } from '../types';
  10. const reFloat = /[-+]?[0-9]*\.?[0-9]+/;
  11. // const rePosInt = /[0-9]+/;
  12. function atomNameListMap(x: string) { return x.split('+').map(B.atomName); }
  13. function listMap(x: string) { return x.split('+').map(x => x.replace(/^["']|["']$/g, '')); }
  14. function rangeMap(x: string) {
  15. const [min, max] = x.split('-').map(x => parseInt(x));
  16. return { min, max };
  17. }
  18. function listOrRangeMap(x: string) {
  19. if (x.includes('-') && x.includes('+')){
  20. const pSplit = x.split('+').map(x => x.replace(/^["']|["']$/g, ''));
  21. const res : number[] =[];
  22. pSplit.forEach( x => {
  23. if (x.includes('-')){
  24. const [min, max] = x.split('-').map(x=>parseInt(x));
  25. for (var i = min; i <= max; i++){
  26. res.push(i);
  27. }
  28. }else{
  29. res.push(parseInt(x));
  30. }
  31. });
  32. return res;
  33. }else if(x.includes('-') && !x.includes('+')){
  34. return rangeMap(x)
  35. }else if(!x.includes('-') && x.includes('+')){
  36. return listMap(x).map(x => parseInt(x))
  37. }else{
  38. return listMap(x).map(x => parseInt(x))
  39. }
  40. }
  41. function elementListMap(x: string) {
  42. return x.split('+').map(B.struct.type.elementSymbol);
  43. }
  44. const sstrucDict: { [k: string]: string } = {
  45. H: 'helix',
  46. S: 'beta',
  47. L: 'none'
  48. };
  49. function sstrucListMap(x: string) {
  50. return {
  51. flags: B.struct.type.secondaryStructureFlags(
  52. x.toUpperCase().split('+').map(ss => sstrucDict[ss] || 'none')
  53. )
  54. };
  55. }
  56. export const properties: PropertyDict = {
  57. symbol: {
  58. '@desc': 'chemical-symbol-list: list of 1- or 2-letter chemical symbols from the periodic table',
  59. '@examples': ['symbol O+N'],
  60. abbr: ['e.'], regex: /[a-zA-Z'"+]+/, map: elementListMap,
  61. level: 'atom-test', property: B.acp('elementSymbol')
  62. },
  63. name: {
  64. '@desc': 'atom-name-list: list of up to 4-letter codes for atoms in proteins or nucleic acids',
  65. '@examples': ['name CA+CB+CG+CD'],
  66. abbr: ['n.'], regex: /[a-zA-Z0-9'"+]+/, map: atomNameListMap,
  67. level: 'atom-test', property: B.ammp('label_atom_id')
  68. },
  69. resn: {
  70. '@desc': 'residue-name-list: list of 3-letter codes for amino acids or list of up to 2-letter codes for nucleic acids',
  71. '@examples': ['resn ASP+GLU+ASN+GLN', 'resn A+G'],
  72. abbr: ['resname', 'r.'], regex: /[a-zA-Z0-9'"+]+/, map: listMap,
  73. level: 'residue-test', property: B.ammp('label_comp_id')
  74. },
  75. resi: {
  76. '@desc': 'residue-identifier-list list of up to 4-digit residue numbers or residue-identifier-range',
  77. '@examples': ['resi 1+10+100+1000', 'resi 1-10'],
  78. abbr: ['resident', 'residue', 'resid', 'i.'], regex: /[0-9+-]+/, map: listOrRangeMap,
  79. level: 'residue-test', property: B.ammp('auth_seq_id')
  80. },
  81. alt: {
  82. '@desc': 'alternate-conformation-identifier-list list of single letters',
  83. '@examples': ['alt A+B', 'alt ""', 'alt ""+A'],
  84. abbr: [], regex: /[a-zA-Z0-9'"+]+/, map: listMap,
  85. level: 'atom-test', property: B.ammp('label_alt_id')
  86. },
  87. chain: {
  88. '@desc': 'chain-identifier-list list of single letters or sometimes numbers',
  89. '@examples': ['chain A'],
  90. abbr: ['c.'], regex: /[a-zA-Z0-9'"+]+/, map: listMap,
  91. level: 'chain-test', property: B.ammp('auth_asym_id')
  92. },
  93. segi: {
  94. '@desc': 'segment-identifier-list list of up to 4 letter identifiers',
  95. '@examples': ['segi lig'],
  96. abbr: ['segid', 's.'], regex: /[a-zA-Z0-9'"+]+/, map: listMap,
  97. level: 'chain-test', property: B.ammp('label_asym_id')
  98. },
  99. flag: {
  100. '@desc': 'flag-number a single integer from 0 to 31',
  101. '@examples': ['flag 0'],
  102. isUnsupported: true,
  103. abbr: ['f.'], regex: /[0-9]+/, map: x => parseInt(x),
  104. level: 'atom-test'
  105. },
  106. numeric_type: {
  107. '@desc': 'type-number a single integer',
  108. '@examples': ['nt. 5'],
  109. isUnsupported: true,
  110. abbr: ['nt.'], regex: /[0-9]+/, map: x => parseInt(x),
  111. level: 'atom-test'
  112. },
  113. text_type: {
  114. '@desc': 'type-string a list of up to 4 letter codes',
  115. '@examples': ['text_type HA+HC'],
  116. isUnsupported: true,
  117. abbr: ['tt.'], regex: /[a-zA-Z0-9'"+]+/, map: listMap,
  118. level: 'atom-test'
  119. },
  120. id: {
  121. '@desc': 'external-index-number a single integer',
  122. '@examples': ['id 23'],
  123. regex: /[0-9+-]+/, map: listOrRangeMap,
  124. level: 'atom-test', property: B.ammp('id')
  125. },
  126. index: {
  127. '@desc': 'internal-index-number a single integer',
  128. '@examples': ['index 11'],
  129. regex: /[0-9+-]+/, map: listOrRangeMap,
  130. level: 'atom-test', property: B.ammp('id')
  131. },
  132. ss: {
  133. '@desc': 'secondary-structure-type list of single letters. Helical regions should be assigned H and sheet regions S. Loop regions can either be assigned L or be blank.',
  134. '@examples': ['ss H+S+L', 'ss S+""'],
  135. abbr: [], regex: /[a-zA-Z'"+]+/, map: sstrucListMap,
  136. level: 'residue-test', property: B.ammp('secondaryStructureFlags')
  137. },
  138. b: {
  139. '@desc': 'comparison-operator b-factor-value a real number',
  140. '@examples': ['b > 10'],
  141. isNumeric: true,
  142. abbr: [], regex: reFloat, map: x => parseFloat(x),
  143. level: 'atom-test', property: B.ammp('B_iso_or_equiv')
  144. },
  145. q: {
  146. '@desc': 'comparison-operator occupancy-value a real number',
  147. '@examples': ['q <0.50'],
  148. isNumeric: true,
  149. abbr: [], regex: reFloat, map: x => parseFloat(x),
  150. level: 'atom-test', property: B.ammp('occupancy')
  151. },
  152. formal_charge: {
  153. '@desc': 'comparison-operator formal charge-value an integer',
  154. '@examples': ['fc. = -1'],
  155. isNumeric: true,
  156. abbr: ['fc.'], regex: reFloat, map: x => parseFloat(x),
  157. level: 'atom-test', property: B.ammp('pdbx_formal_charge')
  158. },
  159. partial_charge: {
  160. '@desc': 'comparison-operator partial charge-value a real number',
  161. '@examples': ['pc. > 1'],
  162. isUnsupported: true,
  163. isNumeric: true,
  164. abbr: ['pc.'], regex: reFloat, map: x => parseFloat(x),
  165. level: 'atom-test'
  166. }
  167. };