void comparatorInstruction(Token instruction, BitSet bs) throws ScriptException {
		int comparator = instruction.tok;
		int property = instruction.intValue;
		float propertyValue = Float.NaN;
		int comparisonValue = ((Integer) instruction.value).intValue();
		BitSet propertyBitSet = null;
		int bitsetComparator = comparator;
		int bitsetBaseValue = comparisonValue;
		int atomCount = viewer.getAtomCount();
		int imax = 0;
		int imin = 0;
		Frame frame = viewer.getFrame();
		for (int i = 0; i < atomCount; ++i) {
			boolean match = false;
			Atom atom = frame.getAtomAt(i);
			switch (property) {
			case Token.atomno:
				propertyValue = atom.getAtomNumber();
				break;
			case Token.atomIndex:
				propertyValue = i;
				break;
			case Token.elemno:
				propertyValue = atom.getElementNumber();
				break;
			case Token.element:
				propertyValue = atom.getAtomicAndIsotopeNumber();
				break;
			case Token.formalCharge:
				propertyValue = atom.getFormalCharge();
				break;
			case Token.site:
				propertyValue = atom.getAtomSite();
				break;
			case Token.symop:
				propertyBitSet = atom.getAtomSymmetry();
				if (bitsetBaseValue >= 1000) {
					/*
					 * symop>=1000 indicates symop1000 + lattice_translation(555) for this the comparision is only with
					 * the translational component; the symop itself must match thus: select symop!=1655 selects all
					 * symop=1 and translation !=655 select symo >=2555 selects all symop=2 and translation >555
					 * 
					 * Note that when normalization is not done, symop=1555 may not be in the base unit cell. Everything
					 * is relative to wherever the base atoms ended up, usually in 555, but not necessarily.
					 * 
					 * The reason this is tied together an atom may have one translation for one symop and another for a
					 * different one.
					 * 
					 * Bob Hanson - 10/2006
					 */

					comparisonValue = bitsetBaseValue % 1000;
					int symop = bitsetBaseValue / 1000 - 1;
					if (symop < 0 || !(match = propertyBitSet.get(symop)))
						continue;
					bitsetComparator = Token.none;
					propertyValue = atom.getSymmetryTranslation(symop);
				}
				break;
			case Token.molecule:
				propertyValue = atom.getMoleculeNumber();
				break;
			case Token.temperature: // 0 - 9999
				propertyValue = atom.getBfactor100();
				if (propertyValue < 0)
					continue;
				break;
			case Token.surfacedistance:
				if (frame.getSurfaceDistanceMax() == 0)
					dots(statementLength, Dots.DOTS_MODE_CALCONLY);
				propertyValue = atom.getSurfaceDistance();
				if (propertyValue < 0)
					continue;
				break;
			case Token.occupancy:
				propertyValue = atom.getOccupancy();
				break;
			case Token.polymerLength:
				propertyValue = atom.getPolymerLength();
				break;
			case Token.resno:
				propertyValue = atom.getResno();
				if (propertyValue == -1)
					continue;
				break;
			case Token._groupID:
				propertyValue = atom.getGroupID();
				if (propertyValue < 0)
					continue;
				break;
			case Token._atomID:
				propertyValue = atom.getSpecialAtomID();
				if (propertyValue < 0)
					continue;
				break;
			case Token._structure:
				propertyValue = getProteinStructureType(atom);
				if (propertyValue == -1)
					continue;
				break;
			case Token.radius:
				propertyValue = atom.getRasMolRadius();
				break;
			case Token.psi:
				propertyValue = atom.getGroupPsi();
				break;
			case Token.phi:
				propertyValue = atom.getGroupPhi();
				break;
			case Token._bondedcount:
				propertyValue = atom.getCovalentBondCount();
				break;
			case Token.model:
				propertyValue = atom.getModelTagNumber();
				break;
			default:
				unrecognizedAtomProperty(property);
			}
			// note that a symop property can be both LE and GT !
			if (propertyBitSet != null) {
				switch (bitsetComparator) {
				case Token.opLT:
					imax = comparisonValue - 1;
					imin = 0;
					break;
				case Token.opLE:
					imax = comparisonValue;
					imin = 0;
					break;
				case Token.opGE:
					imax = propertyBitSet.size();
					imin = comparisonValue - 1;
					break;
				case Token.opGT:
					imax = propertyBitSet.size();
					imin = comparisonValue;
					break;
				case Token.opEQ:
					imax = comparisonValue;
					imin = comparisonValue - 1;
					break;
				case Token.opNE:
					match = !propertyBitSet.get(comparisonValue);
					break;
				}
				if (imin < 0)
					imin = 0;
				if (imax > propertyBitSet.size())
					imax = propertyBitSet.size();
				for (int iBit = imin; iBit < imax; iBit++) {
					if (propertyBitSet.get(iBit)) {
						match = true;
						break;
					}
				}
				if (!match || Float.isNaN(propertyValue))
					comparator = Token.none;
			}
			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);
		}
	}