Jmol developers. Whew! OK, that's about done, I hope. This message
explains what I was up to this last week.
I've refactored the isosurface code into a set of packages all under
org.jmol.jvxl:
+---org.jmol.jvxl
| |
| +---api
| | AtomDataServer.java
| | AtomIndexIterator.java
| | MeshDataServer.java
| | VertexDataServer.java
| |
| +---calc
| | MarchingCubes.java
| | MarchingSquares.java
| |
| +---data
| | AtomData.java
| | JvxlData.java
| | MeshData.java
| | VolumeData.java
| |
| +---readers
| | SurfaceGenerator.java
| | Parameters.java
| | VoxelReader.java
| | VolumeDataReader.java
| | IsoFxyReader.java
| | IsoShapeReader.java
| | AtomDataReader.java
| | IsoMepReader.java
| | IsoMOReader.java
| | IsoSolventReader.java
| | IsoPlaneReader.java
| | VolumeFileReader.java
| | ApbsReader.java
| | CubeReader.java
| | JvxlReader.java
| |
This was quite a bit of work, and there is definitely good news and bad
news.
The good news is that the entire surface creation functionality of Jmol
is now isolated from the Viewer class. That of course means that if ever
anyone wants to use this code in other contexts, it should be quite
straightforward. There are four interfaces:
AtomDataServer.java (provides atom coordinates, radii, etc. --
Viewer)
AtomIndexIterator.java (provides a fast binary tree iterator for
atoms -- Viewer)
VertexDataServer.java (returns vertex indices as they are created
-- Isosurface)
MeshDataServer.java (access to storage for triangles data --
Isosurface)
Four public data structures are utilized:
AtomData.java
JvxlData.java
MeshData.java
VolumeData.java
These pretty much hold what you would expect them to. Mostly they are
just pointers to data held elsewhere, but these classes also now contain
several methods that are intrinsic to their data type. For example,
VolumeData.voxelPtToXYZ(int x, int y, int z) provides a means of quickly
finding out where in space a voxel is based on its integer "CUBE file"
coordinates.
In addition, there is a special parameter class,
Parameters.java
which stores ALL of the various parameters necessary for isosurface
creation and rendering. The main function of the surface generator:
SurfaceGenerator.java
is to set up these parameters, select the right voxel reader (see
below), and then either run generateSurface() or mapColors().
To do an isosurface calculation we need voxel data. That comes from the
readers. As you can see from the hierarchy, there are several types.
Basically we have readers that read file data (APBS, CUBE, JVXL) and
readers that either consume already-prepared data (VolumeDataReader) or
create their own on the fly (IsoMepReader, IsoMOReader,
IsoSurfaceReader, etc.). Some of these rely on an AtomDataServer to
provide atom positions, atomic numbers, and radii. What's interesting, I
think, is that this would not have to be Jmol. It could be any simple
program that can deliver such data. Other readers, such as
IsoShapeReader (for atomic orbitals, spheres, and ellipses) don't need
any additional data. A reader can look as simple as this:
class IsoPlaneReader extends AtomDataReader {
IsoPlaneReader(SurfaceGenerator sg) {
super(sg);
precalculateVoxelData = false;
}
protected void setup() {
super.setup();
doAddHydrogens = false;
getAtoms(params.mep_marginAngstroms, false, false);
setHeader("PLANE", params.thePlane.toString());
setRangesAndAddAtoms(params.solvent_ptsPerAngstrom,
params.solvent_gridMax, Math.min(myAtomCount, 100));
params.cutoff = 0;
}
protected float getValue(int x, int y, int z) {
return volumeData.calcVoxelPlaneDistance(x, y, z);
}
}
So I think you can see that you could add a new "shape" pretty easily.
Just define a getValue() method, provide a keyword for the isosurface
command, and that's about it. In contrast, IsoSurfaceReader is by far
the most involved. This class creates all the
solvent/molecular/cavity/pocket/etc. surfaces you see in Jmol. I don't
want to think about it!
The twin calculation engines
MarchingCubes.java
MarchingSquares.java
are entirely separated from the rest of the business by interfaces.
Their constructors set up the calculation, and a single method does the
rest. For example, a VoxelReader simply does this once the volume data
have been read and parameters are set:
marchingCubes = new MarchingCubes(this, volumeData,
params.isContoured, contourType,
params.cutoff, params.isCutoffAbsolute);
edgeCount = marchingCubes.generateSurfaceData(isXLowToHigh);
That's it. Those two calls deliver a full set of vertices and triangles
to the MeshDataServer (the Isosurface class). I think it's interesting
that only four parameters are sent to the Marching Cubes class -- two to
indicate that we are just using the Marching Cubes to set up a planar
surface that will later be contoured by the Marching Squares algorithm,
a third that is the cutoff all isosurfaces involve, and the last,
whether that cutoff is an absolute value -- for example, when a
CUBE-file based molecular orbital has two phases, positive and negative.
To generate a contoured plane, all we need (after the vertices are
assigned by the Marching Cubes algorithm) is:
marchingSquares = new MarchingSquares(this, volumeData, params.thePlane,
params.nContours, params.thisContour);
marchingSquares.setMinMax(params.valueMappedToRed,
params.valueMappedToBlue);
contourVertexCount =
marchingSquares.generateContourData(jvxlDataIs2dContour);
Miguel pretty much wrote the MarchingCubes code from scratch. I added
the Marching Squares. What that is for is the creation of contours in
planes and f(x,y) curved surfaces. It basically does a 2D version of
Marching Cubes. We use Marching Cubes in the 2D-surface contouring just
to set up the vertexes on the surface that then provide the basis for
"marching". It's kind of neat that this works. I'm have to say I'm
really pleased how it turned out. If you ever need curved-surface
contouring, look no further!
So, overall, it feels great that this is a well-defined separate entity
now -- a real "package" -- a "product" of the Jmol Project that is
basically independent of Jmol itself. I'm not aware of anything out
there quite like it.
Now the bad news.
I'm TIRED!!! I feel like I took Jmol completely apart and put it back
together again. Almost certainly I forgot a nut or a bolt in the
processes. You will find them for me, I am certain. :) Just tonight I
think I have Jmol back together in a way that others can test. So please
do that. Let's call it 11.1.29 and see how it goes.
When you look at that list, it's probably not so surprising that the
"old" Isosurface.java was 5800 lines and 230K of code. I'm happy to say
that this is down to 600 lines and only 20K. But the bad news is that
all that interfacing did cost some file size. The debug-free Jar files
are now about 38K larger than they were before I started hacking (988K
instead of 950K for the applet). I'm quite sensitive to that, but it's
just the way it had to be. I trust people will feel that the benefit of
well-organized code outweighs the compact efficiency of what we had.
Bob Hanson
-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
Jmol-developers mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/jmol-developers