[I tried to send this last night, but I don't think it worked, and even
if it did, this is different!]
You will see some pretty major code changes in Jmol 11.1.14. I wasn't
really planning on this, but I needed a parseFloat() command and
realized that I could with (ahem) a BIT of work (like, 6 hours) change
Parser to all-static methods. This allows it to be used in any class
without having to create a parser object. The only reason it wasn't
static already is that it tracks the current line position in the global
variable "ichNextParse". I making Parser methods all static, that
variable is gone. In its place is the parameter int[] next, which is
really just
int[] next = new int[1];
so that it can be passed by reference to the static methods. This
allowed for some economy of code in just about all of the adapter
methods as well as isosurface (for reading CUBE files) and pmesh (for
reading pmesh files).
The place I wanted this was the context of mixed-type variable
arithmetic. It's interesting to me how this has developed --- In sorting
out all the scattered global settings, I created StateManager and the
GlobalSettings class. That allowed for saving variables in Hashtables,
which allowed for user-defined variables.
myvar = 3
Of course, you couldn't do very much with this -- so I added simple math
and IF/ELSE/ENDIF so that we could at least have a counter:
myvar = myvar - 1
if (myvar = 0);....;else;....;endif;
I was borrowing from the atom expression processor to do the IF logic:
if (myvar = 3 or yourvar = 2)...
and realized it would be helpful to add regular atom expressions:
if ({oxygen} > 2).....
So that forced the need for braces around these expressions. That's when
I realized that %{...} would be helpful in messages and echo text:
echo "there are %{{oxygen}} oxygen atoms in this model"
But this was problematic with set, because there we already use {x y z}
for unitcell definition.
So today I sat down and determined to reconcile IF and SET. I threw out
both arithmetic processors and wrote a nice little Reverse Polish
Notation operand/operator stack class (Eval.Rpn).
(Believe it or not, this was sort of nostalgic for me. I loved RPN in
high school -- What was that little HP calculator that came out in the
early 70s that used RPN, HP-21? I loved that calculator and later
incorporated RPN in a FORTRAN compiler I wrote as a senior project in
high school. -- Ah, back when 16K was all you got. Period.)
This of course took all day, but I think it was well worth it. We can
now do the full range of operator math in IF and SET -- parentheses,
+-*/% < > <= >= = != AND/OR/XOR/NOT.
if {oxygen} > 2 and ({carbon} > {oxygen} or {carbon} > 3) ....
unsaturation = (2 * {_C} + 2 + {_N} - {_H})/2
Both commands use the same method to do the job. The only difference is
that IF always returns a boolean in the end and SET can return boolean,
int, float, String, or Point3f. That's still not fully worked out, and
suggestions are definitely in order here. So the if command now just
looks like this:
boolean ifCmd() throws ScriptException {
return parameterExpression(1, true).booleanValue();
}
and the SET command doesn't look much different:
Object v = parameterExpression((getToken(2).tok == Token.opEQ ? 3 : 2),
false);
if (isSyntaxCheck)
return;
if (v instanceof Boolean) {
setBooleanProperty(key, ((Boolean) v).booleanValue());
} else if (v instanceof Integer) {
setIntProperty(key, ((Integer) v).intValue());
} else if (v instanceof Float) {
setFloatProperty(key, ((Float) v).floatValue());
} else if (v instanceof String) {
setStringProperty(key, (String) v);
} else if (v instanceof Point3f) {
drawPoint(key, (Point3f) v, false);
showString("draw " + key + " " + StateManager.escape((Point3f) v)
+ " off;");
return;
}
That last one is kind of interesting. I was thinking, "What's the best
way to return a point?" We don't have a generic "setPointProperty()"
method. So I thought, well, why not just draw the point. It will be
saved as part of the state that way, and you might even want to see it.
So this leads to constructs such as the following:
c1 = {O5}.xyz
c2 = {N6}.xyz
draw line1 @c1 @c2
That ".xyz" is one of a set of new atom properties designed just for
these purposes. The new set includes:
.x
.y
.z
.xyz
.ident
All the other atom properties are there as well:
.temperature
.atomno
.elemno
.radius
.phi
.psi
.surfacedistance
.partialcharge
.model
.file
.bondcount
._structure
._groupid
.resno
.symop
.site
.formalcharge
.file
.model
LOTS of these -- this is only a partial list. Just let me know if
something isn't there that you want. These are very easy to add.
OK, so this is getting too long. I wanted to run one more idea past you.
OK, if you do this:
x = {oxygen}
you get the number "2" for caffeine, because there are two oxygens. If
you use:
x = {oxygen}.xyz
you get the average position. Actually, you get a POINT at the actual
position, and if the next command is draw on:
x = {oxygen}.xyz; draw on
then you actually SEE that point. (I thought it would be better to leave
these OFF by default.)
OK, but I thought it might be nice to be able to address each of the
oxygens. I tried:
x = {oxygen}.1.xyz
But that gets messed up in the Compiler. So then I tried:
x1 = {oxygen}_1.xyz
but that was seemed strange. So I settled on:
x1 = {oxygen}[1].xyz
which has varients:
x1 = {oxygen}[1-].xyz
x1 = {oxygen}[1-2].xyz
x1 = {oxygen}[-2].xyz
with the obvious meaning.
What's nice about this is that I know I have two oxygens, so it is just
as simple to address them as "1" and "2" rather than their full numbers.
Of course, I could do:
message %{{oxygen}[1].ident} %{{oxygen[2].ident}
(OH, by the way, since it wouldn't make sense to average .ident, doing
this on an atom set with more than one atom just makes a list:
message %{{oxygen}.ident}
gives for caffeine
O9 #9, O11 #11
and for 1crn.pdb:
[THR]1.O #4, [THR]1.OG1 #6, [THR]2.O #11, [THR]2.OG1 #13, [CYS]3.O #18,
[CYS]4.O #24, [PRO]5.O #30, [SER]6.O #37, [SER]6.OG #39, [ILE]7.O #43,
[VAL]8.O #51, [ALA]9.O #58, [ARG]10.O #63, [SER]11.O #74, [SER]11.OG
#76, [ASN]12.O #80, [ASN]12.OD1 #83, [PHE]13.O #88, [ASN]14.O #99,
[ASN]14.OD1 #102, [VAL]15.O #107, [CYS]16.O #114, [ARG]17.O #120,
[LEU]18.O #131, [PRO]19.O #139, [GLY]20.O #146, [THR]21.O #150,
[THR]21.OG1 #152, [PRO]22.O #157, [GLU]23.O #164, [GLU]23.OE1 #168,
[GLU]23.OE2 #169, [ALA]24.O #173, [ILE]25.O #178, [CYS]26.O #186,
[ALA]27.O #192, [THR]28.O #197, [THR]28.OG1 #199, [TYR]29.O #204,
[TYR]29.OH #212, [THR]30.O #216, [THR]30.OG1 #218, [GLY]31.O #223,
[CYS]32.O #227, [ILE]33.O #233, [ILE]34.O #241, [ILE]35.O #249,
[PRO]36.O #257, [GLY]37.O #264, [ALA]38.O #268, [THR]39.O #273,
[THR]39.OG1 #275, [CYS]40.O #280, [PRO]41.O #286, [GLY]42.O #293,
[ASP]43.O #297, [ASP]43.OD1 #300, [ASP]43.OD2 #301, [TYR]44.O #305,
[TYR]44.OH #313, [ALA]45.O #317, [ASN]46.O #322, [ASN]46.OD1 #325,
[ASN]46.OXT #327
I can imagine that this could be quite handy.
OK, enough for now.
Well, one more thing: Think about what you might want to do with
point-based math.
You can do, for example:
x = {oxygen}[1].xyz - {oxygen}[2].xyz
which gives a vector and, interestingly, I think, mixing floats and points is
NOT commutative.
x = 0.0 + {oxygen}[1].xyz - {oxygen}[2].xyz ==> MAGNITUDE of the vector
x = {oxygen}[1].xyz - {oxygen}[2].xyz + 1.0 ==> vector + {1 1 1}
I've added some more mixed-type ideas today.
x = 13.5432 % 3 ===> 12.543
x = 13.5432 % -3 ===> 1.35E+1
x = "testing" % 3 ==> "tes"
x = "testing" % -3 ==> "ing"
for example. Mostly the rule I'm going with is that the left-side operand sets
the generated type.
x = 4.5 + "3.0" ==> 7.5
x = "3.0" + 4.5 ==> 3.04.5
This way we get much more flexibility than the standard Java "anything plus a
string is a string"
Bob
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Jmol-developers mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/jmol-developers