Procházet zdrojové kódy

Merge pull request #3 from yakomaxa/rasmol

Rasmol transpiler added
KoyaS před 2 roky
rodič
revize
82df9d8cad

+ 1 - 1
src/mol-plugin-state/transforms/model.ts

@@ -786,7 +786,7 @@ const StructureSelectionFromScript = PluginStateTransform.BuiltIn({
     from: SO.Molecule.Structure,
     to: SO.Molecule.Structure,
     params: () => ({
-        script: PD.Script({ language: 'vmd', expression: 'all' }),
+        script: PD.Script({ language: 'pymol', expression: 'all' }),
         label: PD.Optional(PD.Text(''))
     })
 })({

+ 4 - 2
src/mol-script/script.ts

@@ -30,7 +30,7 @@ function Script(expression: string = "(sel.atom.all)", language: Script.Language
 }
 
 namespace Script {
-    export type Language = 'mol-script' | 'pymol' | 'vmd' | 'jmol' 
+    export type Language = 'mol-script' | 'pymol' | 'vmd' | 'jmol' | 'rasmol' 
 
     export function is(x: any): x is Script {
         return !!x && typeof (x as Script).expression === 'string' && !!(x as Script).language;
@@ -51,7 +51,9 @@ namespace Script {
 	case 'jmol':
 	    return parse("jmol",script.expression) as Expression;
 	case 'vmd':
-	    return parse("vmd",script.expression) as Expression;	   
+	    return parse("vmd",script.expression) as Expression;
+	case 'rasmol':
+	    return parse("rasmol",script.expression) as Expression;	   
         }
  
         throw new Error('unsupported script language');

+ 3 - 1
src/mol-script/transpilers/all.ts

@@ -9,9 +9,11 @@ import jmol from './jmol/parser'
 //import molQLscript from './molql-script/parser'
 import pymol from './pymol/parser'
 import vmd from './vmd/parser'
+import rasmol from './rasmol/parser'
 
 export default {
     pymol,
     vmd,
-    jmol   
+    jmol,
+    rasmol
 }

+ 20 - 67
src/mol-script/transpilers/pymol/keywords.ts

@@ -65,7 +65,6 @@ export const keywords: KeywordDict = {
     },
     sidechain: {
         '@desc': 'Polymer non-backbone atoms (new in PyMOL 1.6.1)',
-        abbr: ['sc.']
     },
     present: {
         '@desc': 'All atoms with defined coordinates in the current state (used in creating movies)',
@@ -203,77 +202,31 @@ export const keywords: KeywordDict = {
     },
     backbone: {
         '@desc': 'the C, N, CA, and O atoms of a protein and the equivalent atoms in a nucleic acid.',
-        map: () => backboneExpr()
-    },
-    protein: {
-        '@desc': 'protein',
+        map: () => B.struct.generator.atomGroups({
+            'atom-test': B.core.set.has([
+                B.core.type.set(Backbone.protein.concat(ResDict.protein)),
+		B.ammp('label_atom_id')	
+	    ])
+	}),
+    },	    
+    proteinxxxxxx: {
+        '@desc': 'protein................',
 	abbr: ['polymer.protein'],
         map: () => B.struct.generator.atomGroups({
             'residue-test': B.core.set.has([
                 B.core.type.set(ResDict.protein),
                 B.ammp('label_comp_id')
             ])
+	})
+    },
+    nucleicxxxxx: {
+	'@desc': 'protein................',
+	abbr: ['polymer.nucleic'],
+        map: () => B.struct.generator.atomGroups({
+            'residue-test': B.core.set.has([
+                B.core.type.set(ResDict.nucleic),
+                B.ammp('label_comp_id')
+            ])
         })
-    }
+    }				   
 };
-
-function backboneExpr() {
-    return B.struct.combinator.merge([
-        B.struct.generator.queryInSelection({
-            0: proteinExpr(),
-            query: B.struct.generator.atomGroups({
-                'atom-test': B.core.set.has([
-                    h.atomNameSet(Backbone.protein),
-                    B.ammp('label_atom_id')
-                ])
-            })
-        }),
-        B.struct.generator.queryInSelection({
-            0: nucleicExpr(),
-            query: B.struct.generator.atomGroups({
-                'atom-test': B.core.set.has([
-                    h.atomNameSet(Backbone.nucleic),
-                    B.ammp('label_atom_id')
-                ])
-            })
-        })
-    ]);
-}
-
-function proteinExpr() {
-    return B.struct.filter.pick({
-        0: B.struct.generator.atomGroups({
-            'group-by': B.ammp('residueKey')
-        }),
-        test: B.core.set.isSubset([
-            h.atomNameSet(['C', 'N', 'CA', 'O']),
-            B.ammpSet('label_atom_id')
-        ])
-    });
-}
-
-function nucleicExpr() {
-    return B.struct.filter.pick({
-        0: B.struct.generator.atomGroups({
-            'group-by': B.ammp('residueKey')
-        }),
-        test: B.core.logic.and([
-            B.core.set.isSubset([
-                // B.core.type.set([ 'P', 'O1P', 'O2P' ]),
-                h.atomNameSet(['P']),
-                B.ammpSet('label_atom_id')
-            ]),
-            B.core.logic.or([
-                B.core.set.isSubset([
-                    h.atomNameSet(["O3'", "C3'", "C4'", "C5'", "O5'"]),
-                    B.ammpSet('label_atom_id')
-                ]),
-                B.core.set.isSubset([
-                    h.atomNameSet(['O3*', 'C3*', 'C4*', 'C5*', 'O5*']),
-                    B.ammpSet('label_atom_id')
-                ])
-            ])
-        ])
-    });
-}
-

+ 1 - 1
src/mol-script/transpilers/pymol/parser.ts

@@ -59,11 +59,11 @@ const lang = P.MonadicParser.createLanguage({
 
     Expression: function (r : any) {
         return P.MonadicParser.alt(
+	    r.Keywords,
             r.AtomSelectionMacro.map(atomSelectionQuery),
             r.NamedAtomProperties,
             r.Pepseq,
             r.Rep,
-            r.Keywords,
             r.Object
         );
     },

+ 4 - 5
src/mol-script/transpilers/pymol/properties.ts

@@ -10,7 +10,7 @@ const B = MolScriptBuilder;
 import { PropertyDict } from '../types';
 
 const reFloat = /[-+]?[0-9]*\.?[0-9]+/;
-const rePosInt = /[0-9]+/;
+//const rePosInt = /[0-9]+/;
 
 function atomNameListMap(x: string) { return x.split('+').map(B.atomName); }
 function listMap(x: string) { return x.split('+').map(x => x.replace(/^["']|["']$/g, '')); }
@@ -105,15 +105,14 @@ export const properties: PropertyDict = {
     id: {
         '@desc': 'external-index-number a single integer',
         '@examples': ['id 23'],
-        abbr: [], regex: rePosInt, map: x => parseInt(x),
+	regex: /[0-9+-]+/, map: listOrRangeMap,
         level: 'atom-test', property: B.ammp('id')
     },
     index: {
         '@desc': 'internal-index-number a single integer',
         '@examples': ['index 11'],
-        isUnsupported: true,
-        abbr: ['idx.'], regex: rePosInt, map: x => parseInt(x),
-        level: 'atom-test'
+        regex: /[0-9+-]+/, map: listOrRangeMap,
+        level: 'atom-test',property: B.ammp('id')
     },
     ss: {
         '@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.',

+ 27 - 0
src/mol-script/transpilers/rasmol/examples.ts

@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2017 MolQL contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ * @author David Sehnal <david.sehnal@gmail.com>
+ * @author Koya Sakuma
+ */
+
+export default [{
+    name: 'Residue 50 or 135',
+    value: '50 or 135'
+}, {
+    name: 'Atoms with no covalent bonds',
+    value: 'bondcount = 0'
+}, {
+    name: 'All 3-10 helices',
+    value: 'substructure = "helix310"'
+}, {
+    name: 'Metal atoms',
+    value: 'metal'
+}, {
+    name: 'Atoms invloved in aromatic bonds',
+    value: 'isAromatic'
+}, {
+    name: 'Pyrimidine residues',
+    value: 'pyrimidine'
+}]

+ 388 - 0
src/mol-script/transpilers/rasmol/keywords.ts

@@ -0,0 +1,388 @@
+/**                                                                                                                                        
+ * Copyright (c) 2017-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.                                           
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>                                                                                      * @author Panagiotis Tourlas <panagiot_tourlov@hotmail.com>                                                                                 *
+ * @author Koya Sakuma                                                                                                                       * This module was based on jmol transpiler from MolQL and modified in similar manner as pymol and vmd tranpilers.
+**/
+
+
+import { MolScriptBuilder } from '../../../mol-script/language/builder';
+const B = MolScriptBuilder;
+import * as h from '../helper';
+import { KeywordDict } from '../types';
+
+const Backbone = {
+    nucleic: ['P', "O3'", "O5'", "C5'", "C4'", "C3'", 'OP1', 'OP2', 'O3*', 'O5*', 'C5*', 'C4*', 'C3*'],
+    protein: ['C', 'N', 'CA', 'O']
+};
+
+
+function nucleicExpr() {
+  return B.struct.combinator.merge([
+      B.struct.generator.atomGroups({
+	  'residue-test': B.core.set.has([
+              B.set(...['G', 'C', 'A', 'T', 'U', 'I', 'DG', 'DC', 'DA', 'DT', 'DU', 'DI', '+G', '+C', '+A', '+T', '+U', '+I']),
+              B.ammp('label_comp_id')
+	  ])
+      }),
+      B.struct.filter.pick({
+	  0: B.struct.generator.atomGroups({
+              'group-by': B.ammp('residueKey')
+	  }),
+	  test: B.core.logic.and([
+              B.core.rel.eq([ B.struct.atomSet.atomCount(), 1 ]),
+              B.core.rel.eq([ B.ammp('label_atom_id'), B.atomName('P') ]),
+	  ])
+      }),
+      B.struct.filter.pick({
+	  0: B.struct.generator.atomGroups({
+              'group-by': B.ammp('residueKey')
+	  }),
+	  test: B.core.logic.or([
+              B.core.set.isSubset([
+		  h.atomNameSet([ "C1'", "C2'", "O3'", "C3'", "C4'", "C5'", "O5'" ]),
+		  B.ammpSet('label_atom_id')
+              ]),
+              B.core.set.isSubset([
+		  h.atomNameSet([ 'C1*', 'C2*', 'O3*', 'C3*', 'C4*', 'C5*', 'O5*' ]),
+		  B.ammpSet('label_atom_id')
+              ])
+	  ])
+      })
+  ])
+}
+
+
+
+const ResDict = {
+    aliphatic: ['ALA', 'GLY', 'ILE', 'LEU', 'VAL'],
+    amino: ['ALA', 'ARG', 'ASN', 'ASP', 'CYS', 'GLN', 'GLU', 'GLY', 'HIS', 'ILE', 'LEU', 'LYS', 'MET', 'PHE', 'PRO', 'SER', 'THR', 'TRP', 'TYR', 'VAL', 'ASX', 'GLX', 'UNK', ],
+    acidic: ['ASP', 'GLU'],
+    aromatic: ['HIS', 'PHE', 'TRP', 'TYR'],
+    basic: ['ARG', 'HIS', 'LYS'],
+    buried: ['ALA','CYS', 'ILE', 'LEU', 'MET', 'PHE', 'TRP', 'VAL'],
+    cg: ['CYT', 'C', 'GUA', 'G'],
+    cyclic: ['HIS', 'PHE', 'PRO', 'TRP', 'TYR'],
+    hydrophobic: ['ALA', 'GLY', 'ILE', 'LEU', 'MET', 'PHE', 'PRO', 'TRP', 'TYR', 'VAL'],
+    large: ['ARG', 'GLU', 'GLN', 'HIS', 'ILE', 'LEU', 'LYS', 'MET', 'PHE', 'TRP', 'TYR'],
+    medium: ['ASN', 'ASP', 'CYS', 'PRO', 'THR', 'VAL'],
+    small: ['ALA', 'GLY', 'SER'],
+    nucleic: ['A', 'C', 'T', 'G', 'U', 'DA', 'DC', 'DT', 'DG', 'DU'],
+    protein: ['ALA', 'ARG', 'ASN', 'ASP', 'CYS', 'CYX', 'GLN', 'GLU', 'GLY', 'HIS', 'HID', 'HIE', 'HIP', 'ILE', 'LEU', 'LYS', 'MET', 'MSE', 'PHE', 'PRO', 'SER', 'THR', 'TRP', 'TYR', 'VAL'],
+    solvent: ['HOH', 'WAT', 'H20', 'TIP', 'SOL']
+};
+
+
+export const keywords: KeywordDict = {
+  // general terms
+  all: {
+      '@desc': 'all atoms; same as *',
+      abbr: ['*'],
+      map: () => B.struct.generator.all()
+  },
+    none: {
+	'@desc': 'no atoms',
+	map: () => B.struct.generator.empty()
+  },
+    selected: {
+	'@desc': 'atoms that have been selected; defaults to all when a file is first loaded'
+    },
+    unitcell: {
+	'@desc': 'atoms within the current unitcell, which may be offset. This includes atoms on the faces and at the vertices of the unitcell.'
+    },
+    ions: {
+	'@desc': '(specifically the PDB designations "PO4" and "SO4")'
+    },
+    ligand: {
+	'@desc': '(originally "hetero and not solvent"; changed to "!(protein,nucleic,water,UREA)" for Jmol 12.2)'
+    },
+    nucleic: {
+	'@desc': 'any group that (a) has one of the following group names: G, C, A, T, U, I, DG, DC, DA, DT, DU, DI, +G, +C, +A, +T, +U, +I; or (b) can be identified as a group that is only one atom, with name "P"; or (c) has all of the following atoms (prime, \', can replace * here): C1*, C2*, C3*, O3*, C4*, C5*, and O5*.',
+	map: () => nucleicExpr()
+    },
+    purine: {
+	'@desc': 'any nucleic group that (a) has one of the following group names: A, G, I, DA, DG, DI, +A, +G, or +I; or (b) also has atoms N7, C8, and N9.',
+	map: () => B.struct.modifier.intersectBy({
+	    0: nucleicExpr(),
+	    by: B.struct.combinator.merge([
+		B.struct.generator.atomGroups({
+		    'residue-test': B.core.set.has([
+			B.set(...['A', 'G', 'I', 'DA', 'DG', 'DI', '+A', '+G', '+I']),
+			B.ammp('label_comp_id')
+		    ])
+		}),
+		B.struct.filter.pick({
+		    0: B.struct.generator.atomGroups({
+			'group-by': B.ammp('residueKey')
+		    }),
+		    test: B.core.set.isSubset([
+			h.atomNameSet([ 'N7', 'C8', 'N9' ]),
+			B.ammpSet('label_atom_id')
+		    ])
+		})
+	    ])
+	})
+    },
+    pyrimidine: {
+	'@desc': 'any nucleic group that (a) has one of the following group names: C, T, U, DC, DT, DU, +C, +T, +U; or (b) also has atom O2.',
+	map: () => B.struct.modifier.intersectBy({
+	    0: nucleicExpr(),
+	    by: B.struct.combinator.merge([
+		B.struct.generator.atomGroups({
+		    'residue-test': B.core.set.has([
+			B.set(...['C', 'T', 'U', 'DC', 'DT', 'DU', '+C', '+T', '+U']),
+			B.ammp('label_comp_id')
+		    ])
+		}),
+		B.struct.filter.pick({
+		    0: B.struct.generator.atomGroups({
+			'group-by': B.ammp('residueKey')
+		    }),
+		    test: B.core.logic.or([
+			B.core.set.has([
+			    B.ammpSet('label_atom_id'),
+			    B.atomName('O2*')
+			]),
+			B.core.set.has([
+			    B.ammpSet('label_atom_id'),
+			    B.atomName("O2'")
+			])
+		    ])
+		})
+	    ])
+	})
+    },
+    dna: {
+	'@desc': 'any nucleic group that (a) has one of the following group names: DG, DC, DA, DT, DU, DI, T, +G, +C, +A, +T; or (b) has neither atom O2* or O2\'.',
+	map: () => B.struct.modifier.intersectBy({
+	    0: nucleicExpr(),
+	    by: B.struct.combinator.merge([
+		B.struct.generator.atomGroups({
+		    'residue-test': B.core.set.has([
+			B.set(...['DG', 'DC', 'DA', 'DT', 'DU', 'DI', 'T', '+G', '+C', '+A', '+T']),
+			B.ammp('label_comp_id')
+		    ])
+		}),
+		B.struct.filter.pick({
+		    0: B.struct.generator.atomGroups({
+			'group-by': B.ammp('residueKey')
+		    }),
+		    test: B.core.logic.not([
+			B.core.logic.or([
+			    B.core.set.has([
+				B.ammpSet('label_atom_id'),
+				B.atomName('O2*')
+			    ]),
+			    B.core.set.has([
+				B.ammpSet('label_atom_id'),
+				B.atomName("O2'")
+			    ])
+			])
+		    ])
+		})
+	    ])
+	})
+    },
+    rna: {
+	'@desc': 'any nucleic group that (a) has one of the following group names: G, C, A, U, I, +U, +I; or (b) has atom O2* or O2\'.',
+	map: () => B.struct.modifier.intersectBy({
+	    0: nucleicExpr(),
+	    by: B.struct.combinator.merge([
+		B.struct.generator.atomGroups({
+		    'residue-test': B.core.set.has([
+			B.set(...['G', 'C', 'A', 'U', 'I', '+U', '+I']),
+			B.ammp('label_comp_id')
+		    ])
+		}),
+		B.struct.filter.pick({
+		    0: B.struct.generator.atomGroups({
+			'group-by': B.ammp('residueKey')
+		    }),
+		    test: B.core.logic.or([
+			B.core.set.has([
+			    B.ammpSet('label_atom_id'),
+			    B.atomName('O2*')
+			]),
+			B.core.set.has([
+			    B.ammpSet('label_atom_id'),
+			    B.atomName("O2'")
+			])
+		    ])
+		})
+	    ])
+	})
+    },
+    protein: {
+	'@desc': 'defined as a group that (a) has one of the following group names: ALA, ARG, ASN, ASP, CYS, GLN, GLU, GLY, HIS, ILE, LEU}, LYS, MET, PHE, PRO, SER, THR, TRP, TYR, VAL, ASX, GLX, or UNK; or (b) contains PDB atom designations [C, O, CA, and N] bonded correctly; or (c) does not contain "O" but contains [C, CA, and N] bonded correctly; or (d) has only one atom, which has name CA and does not have the group name CA (indicating a calcium atom).',
+	map: () => proteinExpr()	
+    },
+    acidic: {
+	'@desc': 'ASP GLU',
+      map: () => h.resnameExpr(ResDict.acidic)
+  },
+    acyclic: {
+      '@desc': 'amino and not cyclic',
+      map: () => B.struct.modifier.intersectBy({
+	0: h.resnameExpr(ResDict.amino),
+	by: h.invertExpr(h.resnameExpr(ResDict.cyclic))
+    })
+  },
+    aliphatic: {
+      '@desc': 'ALA GLY ILE LEU VAL',
+      map: () => h.resnameExpr(ResDict.aliphatic)
+  },
+    amino: {
+      '@desc': 'all twenty standard amino acids, plus ASX, GLX, UNK',
+      map: () => h.resnameExpr(ResDict.amino)
+  },
+    aromatic: {
+      '@desc': 'HIS PHE TRP TYR (see also "isaromatic" for aromatic bonds)',
+      map: () => h.resnameExpr(ResDict.aromatic)
+  },
+    basic: {
+      '@desc': 'ARG HIS LYS',
+      map: () => h.resnameExpr(ResDict.basic)
+  },
+    buried: {
+      '@desc': 'ALA CYS ILE LEU MET PHE TRP VAL',
+      map: () => h.resnameExpr(ResDict.buried)
+  },
+    charged: {
+      '@desc': 'same as acidic or basic -- ASP GLU, ARG HIS LYS',
+      map: () => h.resnameExpr(ResDict.acidic.concat(ResDict.basic))
+  },
+    cyclic: {
+      '@desc': 'HIS PHE PRO TRP TYR',
+      map: () => h.resnameExpr(ResDict.cyclic)
+  },
+    helix: {
+      '@desc': 'secondary structure-related.',
+      map: () => B.struct.generator.atomGroups({
+	'residue-test': B.core.flags.hasAny([
+          B.struct.type.secondaryStructureFlags(['helix']),
+          B.ammp('secondaryStructureFlags')
+      ])
+    })
+  },
+    hetero: {
+      '@desc': 'PDB atoms designated as HETATM',
+      map: () => B.struct.generator.atomGroups({
+	'atom-test': B.ammp('isHet')
+    })
+  },
+    hydrophobic: {
+      '@desc': 'ALA GLY ILE LEU MET PHE PRO TRP TYR VAL',
+      map: () => h.resnameExpr(ResDict.hydrophobic)
+  },
+    large: {
+      '@desc': 'ARG GLU GLN HIS ILE LEU LYS MET PHE TRP TYR',
+      map: () => h.resnameExpr(ResDict.large)
+  },
+    medium: {
+      '@desc': 'ASN ASP CYS PRO THR VAL',
+      map: () => h.resnameExpr(ResDict.medium)
+  },
+    negative: {
+      '@desc': 'same as acidic -- ASP GLU',
+      map: () => h.resnameExpr(ResDict.acidic)
+  },
+    neutral: {
+      '@desc': 'amino and not (acidic or basic)',
+      map: () => B.struct.modifier.intersectBy({
+	0: h.resnameExpr(ResDict.amino),
+	by: h.invertExpr(h.resnameExpr(ResDict.acidic.concat(ResDict.basic)))
+    })
+  },
+    polar: {
+      '@desc': 'amino and not hydrophobic',
+      map: () => B.struct.modifier.intersectBy({
+	0: h.resnameExpr(ResDict.amino),
+	by: h.invertExpr(h.resnameExpr(ResDict.hydrophobic))
+    })
+  },
+    positive: {
+      '@desc': 'same as basic -- ARG HIS LYS',
+      map: () => h.resnameExpr(ResDict.basic)
+  },
+    sheet: {
+      '@desc': 'secondary structure-related',
+      map: () => B.struct.generator.atomGroups({
+	'residue-test': B.core.flags.hasAny([
+          B.struct.type.secondaryStructureFlags(['sheet']),
+          B.ammp('secondaryStructureFlags')
+      ])
+    })
+  },
+    small: {
+      '@desc': 'ALA GLY SER',
+      map: () => h.resnameExpr(ResDict.small)
+  },
+    turn: {
+      '@desc': 'secondary structure-related',
+      map: () => B.struct.generator.atomGroups({
+	'residue-test': B.core.flags.hasAny([
+          B.struct.type.secondaryStructureFlags(['turn']),
+          B.ammp('secondaryStructureFlags')
+      ])
+    })
+  },
+    alpha: {
+      '@desc': '(*.CA)',
+      map: () => B.struct.generator.atomGroups({
+	'atom-test': B.core.rel.eq([
+          B.atomName('CA'),
+          B.ammp('label_atom_id')
+      ])
+    })
+  },
+    base: {
+      '@desc': '(nucleic bases)'
+  },
+    backbone: {
+      '@desc': '(*.C, *.CA, *.N, and all nucleic other than the bases themselves)',
+      abbr: ['mainchain'],
+      map: () => backboneExpr()
+  },
+    sidechain: {
+	'@desc': '((protein or nucleic) and not backbone)'
+  },
+    solvent: {
+	'@desc': 'PDB "HOH", water, also the connected set of H-O-H in any model',
+	    map: () => h.resnameExpr(ResDict.solvent)	
+    },
+};
+
+function backboneExpr() {
+    return B.struct.combinator.merge([
+        B.struct.generator.queryInSelection({
+            0: proteinExpr(),
+            query: B.struct.generator.atomGroups({
+                'atom-test': B.core.set.has([
+                    h.atomNameSet(Backbone.protein),
+                    B.ammp('label_atom_id')
+                ])
+            })
+        }),
+        B.struct.generator.queryInSelection({
+            0: nucleicExpr(),
+            query: B.struct.generator.atomGroups({
+                'atom-test': B.core.set.has([
+                    h.atomNameSet(Backbone.nucleic),
+                    B.ammp('label_atom_id')
+                ])
+            })
+        })
+    ]);
+}
+
+function proteinExpr() {
+    return B.struct.filter.pick({
+        0: B.struct.generator.atomGroups({
+            'group-by': B.ammp('residueKey')
+        }),
+        test: B.core.set.isSubset([
+            h.atomNameSet(['C', 'N', 'CA', 'O']),
+            B.ammpSet('label_atom_id')
+        ])
+    });
+}
+

+ 63 - 0
src/mol-script/transpilers/rasmol/markdown-docs.ts

@@ -0,0 +1,63 @@
+/* 
+ * Copyright (c) 2017-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.                                           
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>                                                                                     
+ * @author Panagiotis Tourlas <panagiot_tourlov@hotmail.com> 
+ * 
+ * @author Koya Sakuma 
+ * This module is based on jmol transpiler from MolQL and modified in similar manner as pymol and vmd tranpilers.                                             */
+
+import { properties } from './properties';
+import { operators } from './operators';
+import { keywords } from './keywords';
+
+
+const docs: string[] = [
+    'Jmol',
+    '============',
+    '--------------------------------',
+    ''
+];
+
+docs.push(`## Properties\n\n`);
+docs.push('--------------------------------\n');
+for (const name in properties) {
+    if (properties[name].isUnsupported) continue
+
+    const names = [name]
+    if (properties[name].abbr) names.push(...properties[name].abbr!)
+    docs.push(`\`\`\`\n${names.join(', ')}\n\`\`\`\n`);
+
+    if (properties[name]['@desc']) {
+        docs.push(`*${properties[name]['@desc']}*\n`);
+    }
+}
+
+docs.push(`## Operators\n\n`);
+docs.push('--------------------------------\n');
+operators.forEach(o => {
+    if (o.isUnsupported) return
+
+    const names = [o.name]
+    if (o.abbr) names.push(...o.abbr!)
+    docs.push(`\`\`\`\n${names.join(', ')}\n\`\`\`\n`);
+
+    if (o['@desc']) {
+        docs.push(`*${o['@desc']}*\n`);
+    }
+})
+
+docs.push(`## Keywords\n\n`);
+docs.push('--------------------------------\n');
+for (const name in keywords) {
+    if (!keywords[name].map) continue
+
+    const names = [name]
+    if (keywords[name].abbr) names.push(...keywords[name].abbr!)
+    docs.push(`\`\`\`\n${names.join(', ')}\n\`\`\`\n`);
+
+    if (keywords[name]['@desc']) {
+        docs.push(`*${keywords[name]['@desc']}*\n`);
+    }
+}
+
+export default docs.join('\n')

+ 45 - 0
src/mol-script/transpilers/rasmol/operators.ts

@@ -0,0 +1,45 @@
+/*       
+ * Copyright (c) 2017-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.    
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>               
+ * @author Panagiotis Tourlas <panagiot_tourlov@hotmail.com>           
+ *                                                                    
+ * @author Koya Sakuma                                                
+ * This module is based on jmol transpiler from MolQL and modified in similar manner as pymol and vmd tranpilers.                                             \
+ */
+
+
+import * as P from '../../../mol-util/monadic-parser';
+import * as h from '../helper';
+import { MolScriptBuilder } from '../../../mol-script/language/builder';
+const B = MolScriptBuilder;
+import { OperatorList } from '../types';
+//import { Expression } from '../../language/expression';
+
+
+export const operators: OperatorList = [
+  {
+    '@desc': 'Selects atoms that are not included in s1.',
+    '@examples': ['not ARG'],
+    name: 'not',
+    type: h.prefix,
+    rule: P.MonadicParser.alt(P.MonadicParser.regex(/NOT/i).skip(P.MonadicParser.whitespace), P.MonadicParser.string('!').skip(P.MonadicParser.optWhitespace)),
+    map: (op, selection) => h.invertExpr(selection),
+  },
+  {
+    '@desc': 'Selects atoms included in both s1 and s2.',
+    '@examples': ['ASP and .CA'],
+    name: 'and',
+    type: h.binaryLeft,
+    rule: h.infixOp(/AND|&/i),
+    map: (op, selection, by) => B.struct.modifier.intersectBy({ 0: selection, by })
+  },
+  {
+    '@desc': 'Selects atoms included in either s1 or s2.',
+    '@examples': ['ASP or GLU'],
+    name: 'or',
+    type: h.binaryLeft,
+    rule: h.infixOp(/OR|\|/i),
+    map: (op, s1, s2) => B.struct.combinator.merge([s1, s2])
+  }
+]
+

+ 264 - 0
src/mol-script/transpilers/rasmol/parser.ts

@@ -0,0 +1,264 @@
+/**
+ * Copyright (c) 2017-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.                                           
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ * @author Panagiotis Tourlas <panagiot_tourlov@hotmail.com>                                                                     
+ * @author Koya Sakuma
+ * This module is based on jmol tranpiler from MolQL and modified in similar manner as pymol and vmd tranpilers.
+ **/
+
+
+import * as P from '../../../mol-util/monadic-parser';
+import * as h from '../helper';
+import { MolScriptBuilder } from '../../../mol-script/language/builder';
+const B = MolScriptBuilder;
+import { properties, structureMap } from './properties';
+import { operators } from './operators';
+import { keywords } from './keywords';
+import { AtomGroupArgs } from '../types';
+import { Transpiler } from '../transpiler';
+import { OperatorList } from '../types';
+
+//const propertiesDict = h.getPropertyRules(properties);
+
+//const slash = P.MonadicParser.string('/');
+
+
+// <, <=, =, >=, >, !=, and LIKE
+const valueOperators: OperatorList = [
+  {
+    '@desc': 'value comparisons',
+    '@examples': [],
+    name: '=',
+    abbr: ['=='],
+    type: h.binaryLeft,
+    rule: P.MonadicParser.regexp(/\s*(LIKE|>=|<=|=|!=|>|<)\s*/i, 1),
+    map: (op, e1, e2) => {
+      // console.log(op, e1, e2)
+      let expr
+      if (e1 === 'structure') {
+        expr = B.core.flags.hasAny([B.ammp('secondaryStructureFlags'), structureMap(e2)])
+      } else if (e2 === 'structure') {
+        expr = B.core.flags.hasAny([B.ammp('secondaryStructureFlags'), structureMap(e1)])
+      } else if (e1.head === 'core.type.regex') {
+        expr = B.core.str.match([ e1, B.core.type.str([e2]) ])
+      } else if (e2.head === 'core.type.regex') {
+        expr = B.core.str.match([ e2, B.core.type.str([e1]) ])
+      } else if (op.toUpperCase() === 'LIKE') {
+        if (e1.head) {
+          expr = B.core.str.match([
+            B.core.type.regex([`^${e2}$`, 'i']),
+            B.core.type.str([e1])
+          ])
+        } else {
+          expr = B.core.str.match([
+            B.core.type.regex([`^${e1}$`, 'i']),
+            B.core.type.str([e2])
+          ])
+        }
+      }
+      if (!expr) {
+        if (e1.head) e2 = h.wrapValue(e1, e2)
+        if (e2.head) e1 = h.wrapValue(e2, e1)
+        switch (op) {
+          case '=':
+            expr = B.core.rel.eq([e1, e2])
+            break
+          case '!=':
+            expr = B.core.rel.neq([e1, e2])
+            break
+          case '>':
+            expr = B.core.rel.gr([e1, e2])
+            break
+          case '<':
+            expr = B.core.rel.lt([e1, e2])
+            break
+          case '>=':
+            expr = B.core.rel.gre([e1, e2])
+            break
+          case '<=':
+            expr = B.core.rel.lte([e1, e2])
+            break
+          default: throw new Error(`value operator '${op}' not supported`);
+        }
+      }
+      return B.struct.generator.atomGroups({ 'atom-test': expr })
+    }
+  }
+]
+
+function atomExpressionQuery (x: any[]) {
+  const [resno, inscode, chainname, atomname, altloc, ] = x[1]
+  const tests: AtomGroupArgs = {}
+
+  if (chainname) {
+    // should be configurable, there is an option in Jmol to use auth or label
+    tests['chain-test'] = B.core.rel.eq([ B.ammp('auth_asym_id'), chainname ])
+  }
+
+  const resProps = []
+  if (resno) resProps.push(B.core.rel.eq([ B.ammp('auth_seq_id'), resno ]))
+  if (inscode) resProps.push(B.core.rel.eq([ B.ammp('pdbx_PDB_ins_code'), inscode ]))
+  if (resProps.length) tests['residue-test'] = h.andExpr(resProps)
+
+  const atomProps = []
+  if (atomname) atomProps.push(B.core.rel.eq([ B.ammp('auth_atom_id'), atomname ]))
+  if (altloc) atomProps.push(B.core.rel.eq([ B.ammp('label_alt_id'), altloc ]))
+  if (atomProps.length) tests['atom-test'] = h.andExpr(atomProps)
+
+  return B.struct.generator.atomGroups(tests)
+}
+
+const lang = P.MonadicParser.createLanguage({
+  Integer: () => P.MonadicParser.regexp(/-?[0-9]+/).map(Number).desc('integer'),
+
+    Parens: function (r:any) {
+    return P.MonadicParser.alt(
+      r.Parens,
+      r.Operator,
+      r.Expression
+    ).wrap(P.MonadicParser.string('('), P.MonadicParser.string(')'))
+  },
+
+    Expression: function(r:any) {
+	return P.MonadicParser.alt(
+	    r.NamedAtomProperties,
+	    r.Keywords,
+	    r.Resno.lookahead(P.MonadicParser.regexp(/\s*(?!(LIKE|>=|<=|!=|[:^%/.=><]))/i)).map((x:any) => B.struct.generator.atomGroups({
+		'residue-test': B.core.rel.eq([ B.ammp('auth_seq_id'), x ])
+	    })),
+	    r.AtomExpression.map(atomExpressionQuery),
+	    
+	    r.ValueQuery,
+	    
+	    r.Element.map((x: string) => B.struct.generator.atomGroups({
+		'atom-test': B.core.rel.eq([ B.acp('elementSymbol'), B.struct.type.elementSymbol(x) ])
+	    })),
+	    r.Resname.map((x: string) => B.struct.generator.atomGroups({
+		'residue-test': B.core.rel.eq([ B.ammp('label_comp_id'), x ])
+	    })),
+	)
+    },
+
+    NamedAtomProperties: function () {
+        return P.MonadicParser.alt(...h.getNamedPropertyRules(properties)); 
+    },
+
+Operator: function(r:any) {
+    return h.combineOperators(operators, P.MonadicParser.alt(r.Parens, r.Expression))
+  },
+
+AtomExpression: function(r:any) {
+    return P.MonadicParser.seq(
+	P.MonadicParser.lookahead(r.AtomPrefix),
+	P.MonadicParser.seq(
+            r.Resno.or(P.MonadicParser.of(null)),
+            r.Inscode.or(P.MonadicParser.of(null)),
+            r.Chainname.or(P.MonadicParser.of(null)),
+            r.Atomname.or(P.MonadicParser.of(null)),
+            r.Altloc.or(P.MonadicParser.of(null)),
+            r.Model.or(P.MonadicParser.of(null))),	
+    )
+  },
+
+    AtomPrefix: () => P.MonadicParser.regexp(/[0-9:^%/.]/).desc('atom-prefix'),
+    Chainname: () => P.MonadicParser.regexp(/:([A-Za-z]{1,3})/, 1).desc('chainname'),
+    Model: () => P.MonadicParser.regexp(/\/([0-9]+)/, 1).map(Number).desc('model'),
+    Element: () => P.MonadicParser.regexp(/_([A-Za-z]{1,3})/, 1).desc('element'),
+    Atomname: () => P.MonadicParser.regexp(/\.([a-zA-Z0-9]{1,4})/, 1).map(B.atomName).desc('atomname'),
+    Resname: () => P.MonadicParser.regexp(/[a-zA-Z0-9]{1,4}/).desc('resname'),
+    Resno: (r:any) => r.Integer.desc('resno'),
+    Resno2: (r:any) => r.split(',').Integer.desc("resno"),
+    Altloc: () => P.MonadicParser.regexp(/%([a-zA-Z0-9])/, 1).desc('altloc'),
+    Inscode: () => P.MonadicParser.regexp(/\^([a-zA-Z0-9])/, 1).desc('inscode'),
+
+
+//    function listMap(x: string) { return x.split(',').map(x => x.replace(/^["']|["']$/g, '')); }
+
+
+
+    BracketedResname: function (r:any) {
+	return P.MonadicParser.regexp(/\.([a-zA-Z0-9]{1,4})/, 1)
+	    .desc('bracketed-resname')
+	// [0SD]
+    },
+
+    ResnoRange: function (r:any) {
+	return P.MonadicParser.regexp(/\.([\s]){1,3}/, 1)
+	    .desc('resno-range')
+	// 123-200
+	// -12--3
+    },
+
+  Keywords: () => P.MonadicParser.alt(...h.getKeywordRules(keywords)),
+
+Query: function(r:any) {
+    return P.MonadicParser.alt(
+      r.Operator,
+      r.Parens,
+      r.Expression
+    ).trim(P.MonadicParser.optWhitespace)
+  },
+
+  Number: function () {
+    return P.MonadicParser.regexp(/-?(0|[1-9][0-9]*)([.][0-9]+)?([eE][+-]?[0-9]+)?/)
+      .map(Number)
+      .desc('number')
+  },
+
+  String: function () {
+    const w = h.getReservedWords(properties, keywords, operators)
+      .sort(h.strLenSortFn).map(h.escapeRegExp).join('|')
+    return P.MonadicParser.alt(
+      P.MonadicParser.regexp(new RegExp(`(?!(${w}))[A-Z0-9_]+`, 'i')),
+      P.MonadicParser.regexp(/'((?:[^"\\]|\\.)*)'/, 1),
+      P.MonadicParser.regexp(/"((?:[^"\\]|\\.)*)"/, 1).map(x => B.core.type.regex([`^${x}$`, 'i']))
+    )
+  },
+
+Value: function (r:any) {
+    return P.MonadicParser.alt(r.Number, r.String)
+  },
+
+ValueParens: function (r:any) {
+    return P.MonadicParser.alt(
+      r.ValueParens,
+      r.ValueOperator,
+      r.ValueExpressions
+    ).wrap(P.MonadicParser.string('('), P.MonadicParser.string(')'))
+  },
+
+  ValuePropertyNames: function() {
+    return P.MonadicParser.alt(...h.getPropertyNameRules(properties, /LIKE|>=|<=|=|!=|>|<|\)|\s/i))
+  },
+
+ValueOperator: function(r:any) {
+    return h.combineOperators(valueOperators, P.MonadicParser.alt(r.ValueParens, r.ValueExpressions))
+  },
+
+ValueExpressions: function(r:any) {
+    return P.MonadicParser.alt(
+      r.Value,
+      r.ValuePropertyNames
+    )
+  },
+
+ValueQuery: function(r:any) {
+    return P.MonadicParser.alt(
+	r.ValueOperator.map((x:any) => {
+        if (x.head) {
+          if (x.head.startsWith('structure.generator')) return x
+        } else {
+          if (typeof x === 'string' && x.length <= 4) {
+            return B.struct.generator.atomGroups({
+              'residue-test': B.core.rel.eq([ B.ammp('label_comp_id'), x ])
+            })
+          }
+        }
+        throw new Error(`values must be part of an comparison, value '${x}'`)
+      })
+    )
+  }
+})
+
+const transpiler: Transpiler = str => lang.Query.tryParse(str)
+export default transpiler

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 531 - 0
src/mol-script/transpilers/rasmol/properties.ts


+ 36 - 0
src/mol-script/transpilers/rasmol/symbols.ts

@@ -0,0 +1,36 @@
+/*                                                                                                                                           
+ * Copyright (c) 2017-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.                                           
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>                                                                                     
+ * @author Panagiotis Tourlas <panagiot_tourlov@hotmail.com>                                                                                 
+ *                                                                                                                                           
+ * @author Koya Sakuma                                                                                                                       
+ * This module is based on jmol tranpiler from MolQL and modified in similar manner as pymol and vmd tranpilers.                                             \
+*/
+
+import { properties } from './properties';
+import { operators } from './operators';
+import { keywords } from './keywords';
+
+export const Properties: string[] = []
+for (const name in properties) {
+    if (properties[name].isUnsupported) continue
+    Properties.push(name)
+    if (properties[name].abbr) Properties.push(...properties[name].abbr!)
+}
+
+export const Operators: string[] = []
+operators.forEach(o => {
+    if (o.isUnsupported) return
+    Operators.push(o.name)
+    if (o.abbr) Operators.push(...o.abbr)
+})
+
+export const Keywords: string[] = []
+for (const name in keywords) {
+    if (!keywords[name].map) continue
+    Keywords.push(name)
+    if (keywords[name].abbr) Keywords.push(...keywords[name].abbr!)
+}
+
+const _all = { Properties, Operators, Keywords }
+export default _all

Některé soubory nejsou zobrazeny, neboť je v těchto rozdílových datech změněno mnoho souborů