private String useParticleVariables(String s, int frame) {
		if (frame >= model.getTapePointer()) {
			out(ScriptEvent.FAILED, "There is no such frame: " + frame + ". (Total frames: " + model.getTapePointer() + ".)");
			return null;
		}
		int n = model.getNumberOfParticles();
		int lb = s.indexOf("%particle[");
		int rb = s.indexOf("].", lb);
		int lb0 = -1;
		String v;
		int i;
		while (lb != -1 && rb != -1) {
			v = s.substring(lb + 10, rb);
			double x = parseMathExpression(v);
			if (Double.isNaN(x))
				break;
			i = (int) Math.round(x);
			if (i < 0 || i >= n) {
				out(ScriptEvent.FAILED, i + " is an invalid index: must be between 0 and " + (n - 1) + " (inclusive).");
				break;
			}
			v = escapeMetaCharacters(v);
			if (model instanceof MesoModel) {
				GayBerneParticle p = ((MesoModel) model).gb[i];
				s = replaceAll(s, "%particle\\[" + v + "\\]\\.charge", p.charge);
				s = replaceAll(s, "%particle\\[" + v + "\\]\\.friction", p.friction);
				s = replaceAll(s, "%particle\\[" + v + "\\]\\.restraint", p.restraint != null ? p.restraint.k * 100 : 0);
				s = replaceAll(s, "%particle\\[" + v + "\\]\\.mass", p.mass * M_CONVERTER);
				s = replaceAll(s, "%particle\\[" + v + "\\]\\.hx", p.hx * IR_CONVERTER);
				s = replaceAll(s, "%particle\\[" + v + "\\]\\.hy", p.hy * IR_CONVERTER);
				s = replaceAll(s, "%particle\\[" + v + "\\]\\.gamma", p.gamma);
				s = replaceAll(s, "%particle\\[" + v + "\\]\\.custom", p.custom);
				if (frame < 0) {
					s = replaceAll(s, "%particle\\[" + v + "\\]\\.rx", p.rx * R_CONVERTER);
					s = replaceAll(s, "%particle\\[" + v + "\\]\\.ry", p.ry * R_CONVERTER);
					s = replaceAll(s, "%particle\\[" + v + "\\]\\.vx", p.vx * V_CONVERTER);
					s = replaceAll(s, "%particle\\[" + v + "\\]\\.vy", p.vy * V_CONVERTER);
					s = replaceAll(s, "%particle\\[" + v + "\\]\\.ax", p.ax * A_CONVERTER);
					s = replaceAll(s, "%particle\\[" + v + "\\]\\.ay", p.ay * A_CONVERTER);
					s = replaceAll(s, "%particle\\[" + v + "\\]\\.theta", p.theta);
					s = replaceAll(s, "%particle\\[" + v + "\\]\\.omega", p.omega);
					s = replaceAll(s, "%particle\\[" + v + "\\]\\.alpha", p.alpha);
				} else {
					s = replaceAll(s, "%particle\\[" + v + "\\]\\.rx", p.rQ.getQueue1().getData(frame) * R_CONVERTER);
					s = replaceAll(s, "%particle\\[" + v + "\\]\\.ry", p.rQ.getQueue2().getData(frame) * R_CONVERTER);
					s = replaceAll(s, "%particle\\[" + v + "\\]\\.vx", p.vQ.getQueue1().getData(frame) * V_CONVERTER);
					s = replaceAll(s, "%particle\\[" + v + "\\]\\.vy", p.vQ.getQueue2().getData(frame) * V_CONVERTER);
					s = replaceAll(s, "%particle\\[" + v + "\\]\\.ax", p.aQ.getQueue1().getData(frame) * A_CONVERTER);
					s = replaceAll(s, "%particle\\[" + v + "\\]\\.ay", p.aQ.getQueue2().getData(frame) * A_CONVERTER);
					s = replaceAll(s, "%particle\\[" + v + "\\]\\.theta", p.thetaQ.getData(frame));
					s = replaceAll(s, "%particle\\[" + v + "\\]\\.omega", p.omegaQ.getData(frame));
					s = replaceAll(s, "%particle\\[" + v + "\\]\\.alpha", p.alphaQ.getData(frame));
				}
			} else if (model instanceof AtomicModel) {
				Atom a = ((AtomicModel) model).atom[i];
				s = replaceAll(s, "%particle\\[" + v + "\\]\\.charge", a.charge);
				s = replaceAll(s, "%particle\\[" + v + "\\]\\.friction", a.friction);
				s = replaceAll(s, "%particle\\[" + v + "\\]\\.restraint", a.restraint != null ? a.restraint.k * 100 : 0);
				s = replaceAll(s, "%particle\\[" + v + "\\]\\.mass", a.mass * M_CONVERTER);
				s = replaceAll(s, "%particle\\[" + v + "\\]\\.hx", a.hx * IR_CONVERTER);
				s = replaceAll(s, "%particle\\[" + v + "\\]\\.hy", a.hy * IR_CONVERTER);
				s = replaceAll(s, "%particle\\[" + v + "\\]\\.custom", a.custom);
				if (frame < 0) {
					s = replaceAll(s, "%particle\\[" + v + "\\]\\.rx", a.rx * R_CONVERTER);
					s = replaceAll(s, "%particle\\[" + v + "\\]\\.ry", a.ry * R_CONVERTER);
					s = replaceAll(s, "%particle\\[" + v + "\\]\\.vx", a.vx * V_CONVERTER);
					s = replaceAll(s, "%particle\\[" + v + "\\]\\.vy", a.vy * V_CONVERTER);
					s = replaceAll(s, "%particle\\[" + v + "\\]\\.ax", a.ax * A_CONVERTER);
					s = replaceAll(s, "%particle\\[" + v + "\\]\\.ay", a.ay * A_CONVERTER);
				} else {
					s = replaceAll(s, "%particle\\[" + v + "\\]\\.rx", a.rQ.getQueue1().getData(frame) * R_CONVERTER);
					s = replaceAll(s, "%particle\\[" + v + "\\]\\.ry", a.rQ.getQueue2().getData(frame) * R_CONVERTER);
					s = replaceAll(s, "%particle\\[" + v + "\\]\\.vx", a.vQ.getQueue1().getData(frame) * V_CONVERTER);
					s = replaceAll(s, "%particle\\[" + v + "\\]\\.vy", a.vQ.getQueue2().getData(frame) * V_CONVERTER);
					s = replaceAll(s, "%particle\\[" + v + "\\]\\.ax", a.aQ.getQueue1().getData(frame) * A_CONVERTER);
					s = replaceAll(s, "%particle\\[" + v + "\\]\\.ay", a.aQ.getQueue2().getData(frame) * A_CONVERTER);
				}
			}
			lb0 = lb;
			lb = s.indexOf("%particle[");
			if (lb0 == lb) // infinite loop
				break;
			rb = s.indexOf("].", lb);
		}
		if (model instanceof AtomicModel) {
			lb = s.indexOf("%atom[");
			rb = s.indexOf("].", lb);
			while (lb != -1 && rb != -1) {
				v = s.substring(lb + 6, rb);
				double x = parseMathExpression(v);
				if (Double.isNaN(x))
					break;
				i = (int) Math.round(x);
				if (i < 0 || i >= n) {
					out(ScriptEvent.FAILED, i + " is an invalid index: must be between 0 and " + (n - 1) + " (inclusive).");
					break;
				}
				v = escapeMetaCharacters(v);
				Atom a = ((AtomicModel) model).atom[i];
				s = replaceAll(s, "%atom\\[" + v + "\\]\\.id", a.id);
				s = replaceAll(s, "%atom\\[" + v + "\\]\\.mass", a.mass * M_CONVERTER);
				s = replaceAll(s, "%atom\\[" + v + "\\]\\.charge", a.charge);
				s = replaceAll(s, "%atom\\[" + v + "\\]\\.sigma", a.sigma * 0.1);
				s = replaceAll(s, "%atom\\[" + v + "\\]\\.epsilon", a.epsilon);
				s = replaceAll(s, "%atom\\[" + v + "\\]\\.friction", a.friction);
				s = replaceAll(s, "%atom\\[" + v + "\\]\\.restraint", a.restraint != null ? a.restraint.k * 100 : 0);
				s = replaceAll(s, "%atom\\[" + v + "\\]\\.hx", a.hx * IR_CONVERTER);
				s = replaceAll(s, "%atom\\[" + v + "\\]\\.hy", a.hy * IR_CONVERTER);
				s = replaceAll(s, "%atom\\[" + v + "\\]\\.custom", a.custom);
				if (frame < 0) {
					s = replaceAll(s, "%atom\\[" + v + "\\]\\.rx", a.rx * R_CONVERTER);
					s = replaceAll(s, "%atom\\[" + v + "\\]\\.ry", a.ry * R_CONVERTER);
					s = replaceAll(s, "%atom\\[" + v + "\\]\\.vx", a.vx * V_CONVERTER);
					s = replaceAll(s, "%atom\\[" + v + "\\]\\.vy", a.vy * V_CONVERTER);
					s = replaceAll(s, "%atom\\[" + v + "\\]\\.ax", a.ax * A_CONVERTER);
					s = replaceAll(s, "%atom\\[" + v + "\\]\\.ay", a.ay * A_CONVERTER);
				} else {
					s = replaceAll(s, "%atom\\[" + v + "\\]\\.rx", a.rQ.getQueue1().getData(frame) * R_CONVERTER);
					s = replaceAll(s, "%atom\\[" + v + "\\]\\.ry", a.rQ.getQueue2().getData(frame) * R_CONVERTER);
					s = replaceAll(s, "%atom\\[" + v + "\\]\\.vx", a.vQ.getQueue1().getData(frame) * V_CONVERTER);
					s = replaceAll(s, "%atom\\[" + v + "\\]\\.vy", a.vQ.getQueue2().getData(frame) * V_CONVERTER);
					s = replaceAll(s, "%atom\\[" + v + "\\]\\.ax", a.aQ.getQueue1().getData(frame) * A_CONVERTER);
					s = replaceAll(s, "%atom\\[" + v + "\\]\\.ay", a.aQ.getQueue2().getData(frame) * A_CONVERTER);
				}
				lb0 = lb;
				lb = s.indexOf("%atom[");
				if (lb0 == lb) // infinite loop
					break;
				rb = s.indexOf("].", lb);
			}
		}
		return s;
	}