--- trunk/src/selection/SelectionEvaluator.cpp 2005/02/03 14:04:59 282 +++ trunk/src/selection/SelectionEvaluator.cpp 2006/05/17 21:51:42 963 @@ -39,75 +39,108 @@ * such damages. */ +#include #include "selection/SelectionEvaluator.hpp" +#include "primitives/Atom.hpp" +#include "primitives/DirectionalAtom.hpp" +#include "primitives/RigidBody.hpp" +#include "primitives/Molecule.hpp" + namespace oopse { -bool SelectionEvaluator::loadScript(const std::string& filename, const std::string& script) { + SelectionEvaluator::SelectionEvaluator(SimInfo* si) + : info(si), nameFinder(info), distanceFinder(info), indexFinder(info), isLoaded_(false){ + + nStuntDouble = info->getNGlobalAtoms() + info->getNRigidBodies(); + } + + bool SelectionEvaluator::loadScript(const std::string& filename, const std::string& script) { + clearDefinitionsAndLoadPredefined(); this->filename = filename; this->script = script; if (! compiler.compile(filename, script)) { - error = true; - errorMessage = compiler.getErrorMessage(); - return false; + error = true; + errorMessage = compiler.getErrorMessage(); + std::cerr << "SelectionCompiler Error: " << errorMessage << std::endl; + return false; } pc = 0; aatoken = compiler.getAatokenCompiled(); linenumbers = compiler.getLineNumbers(); lineIndices = compiler.getLineIndices(); + + std::vector >::const_iterator i; + + isDynamic_ = false; + for (i = aatoken.begin(); i != aatoken.end(); ++i) { + if (containDynamicToken(*i)) { + isDynamic_ = true; + break; + } + } + + isLoaded_ = true; return true; -} + } -void SelectionEvaluator::clearState() { - for (int i = scriptLevelMax; --i >= 0; ) - stack[i].clear(); - scriptLevel = 0; + void SelectionEvaluator::clearState() { error = false; errorMessage = ""; -} + } -bool SelectionEvaluator::loadScriptString(const std::string& script) { + bool SelectionEvaluator::loadScriptString(const std::string& script) { clearState(); return loadScript("", script); -} + } -bool SelectionEvaluator::loadScriptFile(const std::string& filename) { + bool SelectionEvaluator::loadScriptFile(const std::string& filename) { clearState(); return loadScriptFileInternal(filename); -} + } -bool SelectionEvaluator::loadScriptFileInternal(const string & filename) { + bool SelectionEvaluator::loadScriptFileInternal(const std::string & filename) { + std::ifstream ifs(filename.c_str()); + if (!ifs.is_open()) { + return false; + } -} + const int bufferSize = 65535; + char buffer[bufferSize]; + std::string script; + while(ifs.getline(buffer, bufferSize)) { + script += buffer; + } + return loadScript(filename, script); + } -void SelectionEvaluator::instructionDispatchLoop(){ - + void SelectionEvaluator::instructionDispatchLoop(OOPSEBitSet& bs){ + while ( pc < aatoken.size()) { - statement = aatoken[pc++]; - statementLength = statement.size(); - Token token = statement[0]; - switch (token.tok) { - case Token::define: - define(); - break; - case Token::select: - select(); - break; - default: - unrecognizedCommand(token); - return; - } + statement = aatoken[pc++]; + statementLength = statement.size(); + Token token = statement[0]; + switch (token.tok) { + case Token::define: + define(); + break; + case Token::select: + select(bs); + break; + default: + unrecognizedCommand(token); + return; + } } -} - BitSet SelectionEvaluator::expression(std::vector& code, int pcStart) { - int numberOfAtoms = viewer.getAtomCount(); - BitSet bs; - BitSet[] stack = new BitSet[10]; - int sp = 0; + } - for (int pc = pcStart; ; ++pc) { + OOPSEBitSet SelectionEvaluator::expression(const std::vector& code, int pcStart) { + OOPSEBitSet bs; + std::stack stack; + + for (int pc = pcStart; pc < code.size(); ++pc) { Token instruction = code[pc]; switch (instruction.tok) { @@ -116,46 +149,42 @@ void SelectionEvaluator::instructionDispatchLoop(){ case Token::expressionEnd: break; case Token::all: - bs = stack[sp++] = new BitSet(numberOfAtoms); - for (int i = numberOfAtoms; --i >= 0; ) - bs.set(i); + bs = OOPSEBitSet(nStuntDouble); + bs.setAll(); + stack.push(bs); break; case Token::none: - stack[sp++] = new BitSet(); + bs = OOPSEBitSet(nStuntDouble); + stack.push(bs); break; case Token::opOr: - bs = stack[--sp]; - stack[sp-1].or(bs); + bs = stack.top(); + stack.pop(); + stack.top() |= bs; break; case Token::opAnd: - bs = stack[--sp]; - stack[sp-1].and(bs); + bs = stack.top(); + stack.pop(); + stack.top() &= bs; break; case Token::opNot: - bs = stack[sp - 1]; - notSet(bs); + stack.top().flip(); break; case Token::within: - bs = stack[sp - 1]; - stack[sp - 1] = new BitSet(); - withinInstruction(instruction, bs, stack[sp - 1]); + + withinInstruction(instruction, stack.top()); break; - case Token::selected: - stack[sp++] = copyBitSet(viewer.getSelectionSet()); - break; + //case Token::selected: + // stack.push(getSelectionSet()); + // break; case Token::name: - + stack.push(nameInstruction(boost::any_cast(instruction.value))); break; - case Token::index: - + case Token::index: + stack.push(indexInstruction(instruction.value)); break; - case Token::molname: - - break; - case Token::molindex: - break; case Token::identifier: - stack[sp++] = lookupIdentifierValue((std::string)instruction.value); + stack.push(lookupValue(boost::any_cast(instruction.value))); break; case Token::opLT: case Token::opLE: @@ -163,151 +192,258 @@ void SelectionEvaluator::instructionDispatchLoop(){ case Token::opGT: case Token::opEQ: case Token::opNE: - bs = stack[sp++] = new BitSet(); - comparatorInstruction(instruction, bs); + stack.push(comparatorInstruction(instruction)); break; default: unrecognizedExpression(); } } - if (sp != 1) + if (stack.size() != 1) evalError("atom expression compiler error - stack over/underflow"); - return stack[0]; + + return stack.top(); } - void SelectionEvaluator::comparatorInstruction(Token instruction, BitSet bs) { + OOPSEBitSet SelectionEvaluator::comparatorInstruction(const Token& instruction) { int comparator = instruction.tok; int property = instruction.intValue; - float propertyValue = 0; // just for temperature - int comparisonValue = ((Integer)instruction.value).intValue(); - int numberOfAtoms = viewer.getAtomCount(); - Frame frame = viewer.getFrame(); - for (int i = 0; i < numberOfAtoms; ++i) { - Atom atom = frame.getAtomAt(i); - switch (property) { - case Token::mass: - //propertyValue = atom.getAtomNumber(); - break; - case Token::charge: + float comparisonValue = boost::any_cast(instruction.value); + float propertyValue; + OOPSEBitSet bs(nStuntDouble); + bs.clearAll(); + + SimInfo::MoleculeIterator mi; + Molecule* mol; + Molecule::AtomIterator ai; + Atom* atom; + Molecule::RigidBodyIterator rbIter; + RigidBody* rb; + + for (mol = info->beginMolecule(mi); mol != NULL; mol = info->nextMolecule(mi)) { - break; - case Token::dipole: - - break; - default: - unrecognizedAtomProperty(property); + for(atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) { + compareProperty(atom, bs, property, comparator, comparisonValue); } - bool match = false; - switch (comparator) { - case Token::opLT: - match = propertyValue < comparisonValue; - break; - case Token::opLE: - match = propertyValue <= comparisonValue; - break; - case Token::opGE: - match = propertyValue >= comparisonValue; - break; - case Token::opGT: - match = propertyValue > comparisonValue; - break; - case Token::opEQ: - match = propertyValue == comparisonValue; - break; - case Token::opNE: - match = propertyValue != comparisonValue; - break; - } - if (match) - bs.set(i); + + for (rb = mol->beginRigidBody(rbIter); rb != NULL; rb = mol->nextRigidBody(rbIter)) { + compareProperty(rb, bs, property, comparator, comparisonValue); + } } + + return bs; } -void SelectionEvaluator::withinInstruction(const Token& instruction, BitSet& bs, BitSet& bsResult) + void SelectionEvaluator::compareProperty(StuntDouble* sd, OOPSEBitSet& bs, int property, int comparator, float comparisonValue) { + RealType propertyValue = 0.0; + switch (property) { + case Token::mass: + propertyValue = sd->getMass(); + break; + case Token::charge: + if (sd->isAtom()){ + Atom* atom = static_cast(sd); + propertyValue = getCharge(atom); + } else if (sd->isRigidBody()) { + RigidBody* rb = static_cast(sd); + RigidBody::AtomIterator ai; + Atom* atom; + for (atom = rb->beginAtom(ai); atom != NULL; atom = rb->nextAtom(ai)) { + propertyValue+= getCharge(atom); + } + } + break; + default: + unrecognizedAtomProperty(property); + } + + bool match = false; + switch (comparator) { + case Token::opLT: + match = propertyValue < comparisonValue; + break; + case Token::opLE: + match = propertyValue <= comparisonValue; + break; + case Token::opGE: + match = propertyValue >= comparisonValue; + break; + case Token::opGT: + match = propertyValue > comparisonValue; + break; + case Token::opEQ: + match = propertyValue == comparisonValue; + break; + case Token::opNE: + match = propertyValue != comparisonValue; + break; + } + if (match) + bs.setBitOn(sd->getGlobalIndex()); + } + + void SelectionEvaluator::withinInstruction(const Token& instruction, OOPSEBitSet& bs){ + boost::any withinSpec = instruction.value; + float distance; if (withinSpec.type() == typeid(float)){ - withinDistance(boost::any_cast(withinSpec), bs, bsResult); - return; + distance = boost::any_cast(withinSpec); + } else if (withinSpec.type() == typeid(int)) { + distance = boost::any_cast(withinSpec); + } else { + evalError("casting error in withinInstruction"); + bs.clearAll(); } - evalError("Unrecognized within parameter:" + withinSpec); -} - - void SelectionEvaluator::withinDistance(float distance, const BitSet& bs, const BitSet& bsResult) { - Frame frame = viewer.getFrame(); - for (int i = frame.getAtomCount(); --i >= 0; ) { - if (bs.get(i)) { - Atom atom = frame.getAtomAt(i); - AtomIterator iterWithin = - frame.getWithinIterator(atom, distance); - while (iterWithin.hasNext()) - bsResult.set(iterWithin.next().getAtomIndex()); - } - } + bs = distanceFinder.find(bs, distance); } void SelectionEvaluator::define() { assert(statement.size() >= 3); std::string variable = boost::any_cast(statement[1].value); - - variables.insert(std::make_pair(variable, expression(statement, 2))); + + variables.insert(VariablesType::value_type(variable, expression(statement, 2))); } -} -/** @todo */ -void SelectionEvaluator::predefine(const std::string& script) { + /** @todo */ + void SelectionEvaluator::predefine(const std::string& script) { + if (compiler.compile("#predefine", script)) { - std::vector > aatoken = compiler.getAatokenCompiled(); - if (aatoken.size() != 1) { - evalError("predefinition does not have exactly 1 command:" - + script); - return; - } - std::vector statement = aatoken[0]; - if (statement.size() > 2) { - int tok = statement[1].tok; - if (tok == Token::identifier || (tok & Token::predefinedset) == Token::predefinedset) { - std::string variable = (std::string)statement[1].value; - variables.insert(std::make_pair(variable, statement)); + std::vector > aatoken = compiler.getAatokenCompiled(); + if (aatoken.size() != 1) { + evalError("predefinition does not have exactly 1 command:" + + script); + return; + } + std::vector statement = aatoken[0]; + if (statement.size() > 2) { + int tok = statement[1].tok; + if (tok == Token::identifier || (tok & Token::predefinedset) == Token::predefinedset) { + std::string variable = boost::any_cast(statement[1].value); + variables.insert(VariablesType::value_type(variable, statement)); - } else { - evalError("invalid variable name:" + script); - } - }else { - evalError("bad predefinition length:" + script); - } + } else { + evalError("invalid variable name:" + script); + } + }else { + evalError("bad predefinition length:" + script); + } } else { - evalError("predefined set compile error:" + script + - "\ncompile error:" + compiler.getErrorMessage()); + evalError("predefined set compile error:" + script + + "\ncompile error:" + compiler.getErrorMessage()); } -} + } -void SelectionEvaluator::select(){ - viewer.setSelectionSet(expression(statement, 1)); -} + void SelectionEvaluator::select(OOPSEBitSet& bs){ + bs = expression(statement, 1); + } -BitSet SelectionEvaluator::lookupValue(const std::string& variable){ + OOPSEBitSet SelectionEvaluator::lookupValue(const std::string& variable){ + OOPSEBitSet bs(nStuntDouble); std::map::iterator i = variables.find(variable); - + if (i != variables.end()) { - if (i->second.type() == typeid(BitSet)) { - return boost::any_cast(i->second); - } else if (i->second.type() == typeid(std::vector)){ - BitSet bs = expression(boost::any_cast(i->second), 2); - i->second = bs; /**@todo fixme */ - return bs; - } + if (i->second.type() == typeid(OOPSEBitSet)) { + return boost::any_cast(i->second); + } else if (i->second.type() == typeid(std::vector)){ + bs = expression(boost::any_cast >(i->second), 2); + i->second = bs; /**@todo fixme */ + return bs; + } + } else { + unrecognizedIdentifier(variable); } -} + return bs; + } + OOPSEBitSet SelectionEvaluator::nameInstruction(const std::string& name){ + + return nameFinder.match(name); + + } + + bool SelectionEvaluator::containDynamicToken(const std::vector& tokens){ + std::vector::const_iterator i; + for (i = tokens.begin(); i != tokens.end(); ++i) { + if (i->tok & Token::dynamic) { + return true; + } + } + + return false; + } + + void SelectionEvaluator::clearDefinitionsAndLoadPredefined() { + variables.clear(); + //load predefine + //predefine(); + } + + OOPSEBitSet SelectionEvaluator::evaluate() { + OOPSEBitSet bs(nStuntDouble); + if (isLoaded_) { + pc = 0; + instructionDispatchLoop(bs); + } + + return bs; + } + + OOPSEBitSet SelectionEvaluator::indexInstruction(const boost::any& value) { + OOPSEBitSet bs(nStuntDouble); + + if (value.type() == typeid(int)) { + int index = boost::any_cast(value); + if (index < 0 || index >= bs.size()) { + invalidIndex(index); + } else { + bs = indexFinder.find(index); + } + } else if (value.type() == typeid(std::pair)) { + std::pair indexRange= boost::any_cast >(value); + assert(indexRange.first <= indexRange.second); + if (indexRange.first < 0 || indexRange.second >= bs.size()) { + invalidIndexRange(indexRange); + }else { + bs = indexFinder.find(indexRange.first, indexRange.second); + } + } + + return bs; + } + + + RealType SelectionEvaluator::getCharge(Atom* atom) { + RealType charge =0.0; + AtomType* atomType = atom->getAtomType(); + if (atomType->isCharge()) { + GenericData* data = atomType->getPropertyByName("Charge"); + if (data != NULL) { + DoubleGenericData* doubleData= dynamic_cast(data); + + if (doubleData != NULL) { + charge = doubleData->getData(); + + } else { + sprintf( painCave.errMsg, + "Can not cast GenericData to DoubleGenericData\n"); + painCave.severity = OOPSE_ERROR; + painCave.isFatal = 1; + simError(); + } + } + } + + return charge; + } + }