| 43 |  | namespace oopse { | 
| 44 |  |  | 
| 45 |  |  | 
| 46 | + | bool SelectionEvaluator::loadScript(const std::string& filename, const std::string& script) { | 
| 47 | + | this->filename = filename; | 
| 48 | + | this->script = script; | 
| 49 | + | if (! compiler.compile(filename, script)) { | 
| 50 | + | error = true; | 
| 51 | + | errorMessage = compiler.getErrorMessage(); | 
| 52 | + | return false; | 
| 53 | + | } | 
| 54 | + |  | 
| 55 | + | pc = 0; | 
| 56 | + | aatoken = compiler.getAatokenCompiled(); | 
| 57 | + | linenumbers = compiler.getLineNumbers(); | 
| 58 | + | lineIndices = compiler.getLineIndices(); | 
| 59 | + | return true; | 
| 60 |  | } | 
| 61 | + |  | 
| 62 | + | void SelectionEvaluator::clearState() { | 
| 63 | + | for (int i = scriptLevelMax; --i >= 0; ) | 
| 64 | + | stack[i] = null; | 
| 65 | + | scriptLevel = 0; | 
| 66 | + | error = false; | 
| 67 | + | errorMessage = null; | 
| 68 | + | } | 
| 69 | + |  | 
| 70 | + | bool SelectionEvaluator::loadScriptString(const std::string& script) { | 
| 71 | + | clearState(); | 
| 72 | + | return loadScript(null, script); | 
| 73 | + | } | 
| 74 | + |  | 
| 75 | + | bool SelectionEvaluator::loadScriptFile(const std::string& filename) { | 
| 76 | + | clearState(); | 
| 77 | + | return loadScriptFileInternal(filename); | 
| 78 | + | } | 
| 79 | + |  | 
| 80 | + |  | 
| 81 | + | void SelectionEvaluator::instructionDispatchLoop(){ | 
| 82 | + |  | 
| 83 | + | while ( pc < aatoken.length) { | 
| 84 | + | statement = aatoken[pc++]; | 
| 85 | + | statementLength = statement.length; | 
| 86 | + | Token token = statement[0]; | 
| 87 | + | switch (token.tok) { | 
| 88 | + | case Token.define: | 
| 89 | + | define(); | 
| 90 | + | break; | 
| 91 | + | case Token.select: | 
| 92 | + | select(); | 
| 93 | + | break; | 
| 94 | + | default: | 
| 95 | + | unrecognizedCommand(token); | 
| 96 | + | return; | 
| 97 | + | } | 
| 98 | + | } | 
| 99 | + | } | 
| 100 | + |  | 
| 101 | + | void SelectionEvaluator::predefine(String script) { | 
| 102 | + | if (compiler.compile("#predefine", script)) { | 
| 103 | + | Token [][] aatoken = compiler.getAatokenCompiled(); | 
| 104 | + | if (aatoken.length != 1) { | 
| 105 | + | viewer.scriptStatus("predefinition does not have exactly 1 command:" | 
| 106 | + | + script); | 
| 107 | + | return; | 
| 108 | + | } | 
| 109 | + | Token[] statement = aatoken[0]; | 
| 110 | + | if (statement.length > 2) { | 
| 111 | + | int tok = statement[1].tok; | 
| 112 | + | if (tok == Token.identifier || | 
| 113 | + | (tok & Token.predefinedset) == Token.predefinedset) { | 
| 114 | + | String variable = (String)statement[1].value; | 
| 115 | + | variables.put(variable, statement); | 
| 116 | + | } else { | 
| 117 | + | viewer.scriptStatus("invalid variable name:" + script); | 
| 118 | + | } | 
| 119 | + | } else { | 
| 120 | + | viewer.scriptStatus("bad predefinition length:" + script); | 
| 121 | + | } | 
| 122 | + | } else { | 
| 123 | + | viewer.scriptStatus("predefined set compile error:" + script + | 
| 124 | + | "\ncompile error:" + compiler.getErrorMessage()); | 
| 125 | + | } | 
| 126 | + | } | 
| 127 | + |  | 
| 128 | + |  | 
| 129 | + |  | 
| 130 | + | BitSet SelectionEvaluator::expression(Token[] code, int pcStart) throws ScriptException { | 
| 131 | + | int numberOfAtoms = viewer.getAtomCount(); | 
| 132 | + | BitSet bs; | 
| 133 | + | BitSet[] stack = new BitSet[10]; | 
| 134 | + | int sp = 0; | 
| 135 | + |  | 
| 136 | + | for (int pc = pcStart; ; ++pc) { | 
| 137 | + | Token instruction = code[pc]; | 
| 138 | + | if (logMessages) | 
| 139 | + | viewer.scriptStatus("instruction=" + instruction); | 
| 140 | + | switch (instruction.tok) { | 
| 141 | + | case Token.expressionBegin: | 
| 142 | + | break; | 
| 143 | + | case Token.expressionEnd: | 
| 144 | + | break expression_loop; | 
| 145 | + | case Token.all: | 
| 146 | + | bs = stack[sp++] = new BitSet(numberOfAtoms); | 
| 147 | + | for (int i = numberOfAtoms; --i >= 0; ) | 
| 148 | + | bs.set(i); | 
| 149 | + | break; | 
| 150 | + | case Token.none: | 
| 151 | + | stack[sp++] = new BitSet(); | 
| 152 | + | break; | 
| 153 | + | case Token.opOr: | 
| 154 | + | bs = stack[--sp]; | 
| 155 | + | stack[sp-1].or(bs); | 
| 156 | + | break; | 
| 157 | + | case Token.opAnd: | 
| 158 | + | bs = stack[--sp]; | 
| 159 | + | stack[sp-1].and(bs); | 
| 160 | + | break; | 
| 161 | + | case Token.opNot: | 
| 162 | + | bs = stack[sp - 1]; | 
| 163 | + | notSet(bs); | 
| 164 | + | break; | 
| 165 | + | case Token.within: | 
| 166 | + | bs = stack[sp - 1]; | 
| 167 | + | stack[sp - 1] = new BitSet(); | 
| 168 | + | withinInstruction(instruction, bs, stack[sp - 1]); | 
| 169 | + | break; | 
| 170 | + | case Token.selected: | 
| 171 | + | stack[sp++] = copyBitSet(viewer.getSelectionSet()); | 
| 172 | + | break; | 
| 173 | + | case Token.y: | 
| 174 | + | case Token.amino: | 
| 175 | + | case Token.backbone: | 
| 176 | + | case Token.solvent: | 
| 177 | + | case Token.identifier: | 
| 178 | + | case Token.sidechain: | 
| 179 | + | case Token.surface: | 
| 180 | + | stack[sp++] = lookupIdentifierValue((String)instruction.value); | 
| 181 | + | break; | 
| 182 | + | case Token.opLT: | 
| 183 | + | case Token.opLE: | 
| 184 | + | case Token.opGE: | 
| 185 | + | case Token.opGT: | 
| 186 | + | case Token.opEQ: | 
| 187 | + | case Token.opNE: | 
| 188 | + | bs = stack[sp++] = new BitSet(); | 
| 189 | + | comparatorInstruction(instruction, bs); | 
| 190 | + | break; | 
| 191 | + | default: | 
| 192 | + | unrecognizedExpression(); | 
| 193 | + | } | 
| 194 | + | } | 
| 195 | + | if (sp != 1) | 
| 196 | + | evalError("atom expression compiler error - stack over/underflow"); | 
| 197 | + | return stack[0]; | 
| 198 | + | } | 
| 199 | + |  | 
| 200 | + |  | 
| 201 | + |  | 
| 202 | + | void SelectionEvaluator::comparatorInstruction(Token instruction, BitSet bs) { | 
| 203 | + | int comparator = instruction.tok; | 
| 204 | + | int property = instruction.intValue; | 
| 205 | + | float propertyValue = 0; // just for temperature | 
| 206 | + | int comparisonValue = ((Integer)instruction.value).intValue(); | 
| 207 | + | int numberOfAtoms = viewer.getAtomCount(); | 
| 208 | + | Frame frame = viewer.getFrame(); | 
| 209 | + | for (int i = 0; i < numberOfAtoms; ++i) { | 
| 210 | + | Atom atom = frame.getAtomAt(i); | 
| 211 | + | switch (property) { | 
| 212 | + | case Token.atomno: | 
| 213 | + | propertyValue = atom.getAtomNumber(); | 
| 214 | + | break; | 
| 215 | + | case Token.elemno: | 
| 216 | + | propertyValue = atom.getElementNumber(); | 
| 217 | + | break; | 
| 218 | + | case Token.temperature: | 
| 219 | + | propertyValue = atom.getBfactor100(); | 
| 220 | + | if (propertyValue < 0) | 
| 221 | + | continue; | 
| 222 | + | propertyValue /= 100; | 
| 223 | + | break; | 
| 224 | + | case Token._atomID: | 
| 225 | + | propertyValue = atom.getSpecialAtomID(); | 
| 226 | + | if (propertyValue < 0) | 
| 227 | + | continue; | 
| 228 | + | break; | 
| 229 | + | case Token._structure: | 
| 230 | + | propertyValue = getProteinStructureType(atom); | 
| 231 | + | if (propertyValue == -1) | 
| 232 | + | continue; | 
| 233 | + | break; | 
| 234 | + | case Token.radius: | 
| 235 | + | propertyValue = atom.getRasMolRadius(); | 
| 236 | + | break; | 
| 237 | + | case Token._bondedcount: | 
| 238 | + | propertyValue = atom.getCovalentBondCount(); | 
| 239 | + | break; | 
| 240 | + | case Token.model: | 
| 241 | + | propertyValue = atom.getModelTagNumber(); | 
| 242 | + | break; | 
| 243 | + | default: | 
| 244 | + | unrecognizedAtomProperty(property); | 
| 245 | + | } | 
| 246 | + | boolean match = false; | 
| 247 | + | switch (comparator) { | 
| 248 | + | case Token.opLT: | 
| 249 | + | match = propertyValue < comparisonValue; | 
| 250 | + | break; | 
| 251 | + | case Token.opLE: | 
| 252 | + | match = propertyValue <= comparisonValue; | 
| 253 | + | break; | 
| 254 | + | case Token.opGE: | 
| 255 | + | match = propertyValue >= comparisonValue; | 
| 256 | + | break; | 
| 257 | + | case Token.opGT: | 
| 258 | + | match = propertyValue > comparisonValue; | 
| 259 | + | break; | 
| 260 | + | case Token.opEQ: | 
| 261 | + | match = propertyValue == comparisonValue; | 
| 262 | + | break; | 
| 263 | + | case Token.opNE: | 
| 264 | + | match = propertyValue != comparisonValue; | 
| 265 | + | break; | 
| 266 | + | } | 
| 267 | + | if (match) | 
| 268 | + | bs.set(i); | 
| 269 | + | } | 
| 270 | + | } | 
| 271 | + |  | 
| 272 | + | void SelectionEvaluator::withinInstruction(Token instruction, BitSet bs, BitSet bsResult) | 
| 273 | + |  | 
| 274 | + | Object withinSpec = instruction.value; | 
| 275 | + | if (withinSpec instanceof Float) { | 
| 276 | + | withinDistance(((Float)withinSpec).floatValue(), bs, bsResult); | 
| 277 | + | return; | 
| 278 | + | } | 
| 279 | + | evalError("Unrecognized within parameter:" + withinSpec); | 
| 280 | + | } | 
| 281 | + |  | 
| 282 | + | void SelectionEvaluator::withinDistance(float distance, BitSet bs, BitSet bsResult) { | 
| 283 | + | Frame frame = viewer.getFrame(); | 
| 284 | + | for (int i = frame.getAtomCount(); --i >= 0; ) { | 
| 285 | + | if (bs.get(i)) { | 
| 286 | + | Atom atom = frame.getAtomAt(i); | 
| 287 | + | AtomIterator iterWithin = | 
| 288 | + | frame.getWithinIterator(atom, distance); | 
| 289 | + | while (iterWithin.hasNext()) | 
| 290 | + | bsResult.set(iterWithin.next().getAtomIndex()); | 
| 291 | + | } | 
| 292 | + | } | 
| 293 | + | } | 
| 294 | + |  | 
| 295 | + | void SelectionEvaluator::define() throws ScriptException { | 
| 296 | + | String variable = (String)statement[1].value; | 
| 297 | + | variables.put(variable, (expression(statement, 2))); | 
| 298 | + | } | 
| 299 | + | } | 
| 300 | + |  | 
| 301 | + | void SelectionEvaluator::predefine(Token[] statement) { | 
| 302 | + | String variable = (String)statement[1].value; | 
| 303 | + | variables.put(variable, statement); | 
| 304 | + | } | 
| 305 | + |  | 
| 306 | + | void SelectionEvaluator::select(){ | 
| 307 | + | // NOTE this is called by restrict() | 
| 308 | + | if (statementLength == 1) { | 
| 309 | + | viewer.selectAll(); | 
| 310 | + | if (!viewer.getRasmolHydrogenSetting()) | 
| 311 | + | viewer.excludeSelectionSet(getHydrogenSet()); | 
| 312 | + | if (!viewer.getRasmolHeteroSetting()) | 
| 313 | + | viewer.excludeSelectionSet(getHeteroSet()); | 
| 314 | + | } else { | 
| 315 | + | viewer.setSelectionSet(expression(statement, 1)); | 
| 316 | + | } | 
| 317 | + | viewer.scriptStatus("" + viewer.getSelectionCount() + " atoms selected"); | 
| 318 | + | } | 
| 319 | + |  | 
| 320 | + | } |