Java tutorial
/** * Title: Force Field X. * * Description: Force Field X - Software for Molecular Biophysics. * * Copyright: Copyright (c) Michael J. Schnieders 2001-2017. * * This file is part of Force Field X. * * Force Field X is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3 as published by * the Free Software Foundation. * * Force Field X is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * Force Field X; if not, write to the Free Software Foundation, Inc., 59 Temple * Place, Suite 330, Boston, MA 02111-1307 USA * * Linking this library statically or dynamically with other modules is making a * combined work based on this library. Thus, the terms and conditions of the * GNU General Public License cover the whole combination. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent modules, and * to copy and distribute the resulting executable under terms of your choice, * provided that you also meet, for each linked independent module, the terms * and conditions of the license of that module. An independent module is a * module which is not derived from or based on this library. If you modify this * library, you may extend this exception to your version of the library, but * you are not obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package ffx.potential; import java.io.File; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.Enumeration; import java.util.List; import java.util.ListIterator; import java.util.Vector; import java.util.logging.Level; import java.util.logging.Logger; import javax.media.j3d.Appearance; import javax.media.j3d.BoundingSphere; import javax.media.j3d.BranchGroup; import javax.media.j3d.ColoringAttributes; import javax.media.j3d.GeometryArray; import javax.media.j3d.Group; import javax.media.j3d.LineArray; import javax.media.j3d.LineAttributes; import javax.media.j3d.Link; import javax.media.j3d.Material; import javax.media.j3d.Node; import javax.media.j3d.RenderingAttributes; import javax.media.j3d.Shape3D; import javax.media.j3d.SharedGroup; import javax.media.j3d.Switch; import javax.media.j3d.Transform3D; import javax.media.j3d.TransformGroup; import javax.vecmath.Color3f; import javax.vecmath.Matrix3d; import javax.vecmath.Point3d; import javax.vecmath.Vector3d; import com.sun.j3d.utils.picking.PickTool; import org.apache.commons.configuration.CompositeConfiguration; import org.jdesktop.j3d.loaders.vrml97.VrmlLoader; import org.jdesktop.j3d.loaders.vrml97.VrmlScene; import edu.rit.pj.ParallelTeam; import ffx.crystal.Crystal; import ffx.numerics.VectorMath; import ffx.potential.bonded.Atom; import ffx.potential.bonded.Bond; import ffx.potential.bonded.MSGroup; import ffx.potential.bonded.MSNode; import ffx.potential.bonded.Molecule; import ffx.potential.bonded.Polymer; import ffx.potential.bonded.ROLS; import ffx.potential.bonded.RendererCache; import ffx.potential.bonded.Residue; import ffx.potential.bonded.Residue.ResiduePosition; import ffx.potential.parameters.ForceField; import static ffx.potential.bonded.Residue.ResiduePosition.FIRST_RESIDUE; import static ffx.potential.bonded.Residue.ResiduePosition.LAST_RESIDUE; import static ffx.potential.bonded.Residue.ResiduePosition.MIDDLE_RESIDUE; /** * The MolecularAssembly class is a collection of Polymers, Hetero Molecules, * Ions and Water * * @author Michael J. Schnieders * */ public class MolecularAssembly extends MSGroup { private static final Logger logger = Logger.getLogger(MolecularAssembly.class.getName()); private static final long serialVersionUID = 1L; /** * Constant <code>MultiScaleLevel=4</code> */ public static final int MultiScaleLevel = 4; /** * Constant <code>KCAL_TO_KJ=4.184</code> */ public static final double KCAL_TO_KJ = 4.184; private static double[] a = new double[3]; // MolecularSystem member variables private File file; protected ForceField forceField; private ForceFieldEnergy potentialEnergy; private CompositeConfiguration properties; private Vector3d offset; private int cycles = 1; private int currentCycle = 1; private List<String> altLoc = null; // Data Nodes private final MSNode ions = new MSNode("Ions"); private final MSNode water = new MSNode("Waters"); private final MSNode molecules = new MSNode("Hetero Molecules"); // 3D Graphics Nodes - There is a diagram explaining the MolecularAssembly // Scenegraph below private BranchGroup branchGroup; private TransformGroup originToRot; private Transform3D originToRotT3D; private Vector3d originToRotV3D; private TransformGroup rotToCOM; private Transform3D rotToCOMT3D; private Vector3d rotToCOMV3D; private BranchGroup base; private Switch switchGroup; private Shape3D wire; private BranchGroup vrml; private TransformGroup vrmlTG; private Transform3D vrmlTd; private BranchGroup childNodes; private Atom[] atomLookUp; private LineAttributes lineAttributes; private File vrmlFile = null; private URL vrmlURL = null; private boolean visible = false; private final ArrayList<BranchGroup> myNewShapes = new ArrayList<>(); private final List<String> headerLines = new ArrayList<>(); // Constructors /** * <p> * Constructor for MolecularAssembly.</p> * * @param name a {@link java.lang.String} object. */ public MolecularAssembly(String name) { super(name); getAtomNode().setName("MacroMolecules"); add(molecules); add(ions); add(water); } /** * <p> * Constructor for MolecularAssembly.</p> * * @param name a {@link java.lang.String} object. * @param Polymers a {@link ffx.potential.bonded.MSNode} object. */ public MolecularAssembly(String name, MSNode Polymers) { super(name, Polymers); } public MolecularAssembly(String name, MSNode Polymers, CompositeConfiguration properties) { this(name, Polymers); this.properties = properties; } /** * <p> * Setter for the field <code>forceField</code>.</p> * * @param forceField a {@link ffx.potential.parameters.ForceField} object. */ public void setForceField(ForceField forceField) { this.forceField = forceField; } public void setPropertiesFromForceField() { this.properties = forceField.getProperties(); } /** * <p> * setPotential</p> * * @param potentialEnergy a {@link ffx.potential.ForceFieldEnergy} object. */ public void setPotential(ForceFieldEnergy potentialEnergy) { this.potentialEnergy = potentialEnergy; } /** * <p> * Getter for the field <code>potentialEnergy</code>.</p> * * @return a {@link ffx.potential.ForceFieldEnergy} object. */ public ForceFieldEnergy getPotentialEnergy() { return potentialEnergy; } public ParallelTeam getParallelTeam() { if (potentialEnergy != null) { return potentialEnergy.getParallelTeam(); } else { return null; } } public ResiduePosition getResiduePosition(int residueNumber) { ResiduePosition position; int numberOfResidues = 0; Polymer polymers[] = getChains(); int nPolymers = polymers.length; for (int i = 0; i < nPolymers; i++) { Polymer polymer = polymers[i]; ArrayList<Residue> residues = polymer.getResidues(); numberOfResidues += residues.size(); } if (residueNumber == 0) { position = FIRST_RESIDUE; } else if (residueNumber == numberOfResidues - 1) { position = LAST_RESIDUE; } else { position = MIDDLE_RESIDUE; } return position; } /** * Adds a header line to this MolecularAssembly (particularly for PDB * formats) * * @param line Line to add. */ public void addHeaderLine(String line) { headerLines.add(line); } /** * Gets the header lines associated with this MolecularAssembly * (particularly for PDB) * * @return Header lines. */ public String[] getHeaderLines() { String[] ret = new String[headerLines.size()]; headerLines.toArray(ret); return ret; } /** * <p> * getCrystal</p> * * @return a {@link ffx.crystal.Crystal} object. */ public Crystal getCrystal() { if (potentialEnergy == null) { return null; } return potentialEnergy.getCrystal(); } /** * <p> * Getter for the field <code>forceField</code>.</p> * * @return a {@link ffx.potential.parameters.ForceField} object. */ public ForceField getForceField() { return forceField; } /** * <p> * addAltLocation</p> * * @param s a {@link java.lang.String} object. */ public void addAltLocation(String s) { if (altLoc == null) { altLoc = new Vector<String>(); } if (!altLoc.contains(s)) { altLoc.add(s); } } /** * {@inheritDoc} */ @Override public MSNode addMSNode(MSNode o) { ArrayList Polymers = getAtomNodeList(); if (o instanceof Atom) { Atom atom = (Atom) o; if (atom.isModRes()) { return getResidue(atom, true, Residue.ResidueType.AA); } else if (!atom.isHetero()) { return getResidue(atom, true); } else { return getMolecule(atom, true); } } else if (o instanceof Residue) { Residue residue = (Residue) o; Character chainID = residue.getChainID(); String segID = residue.getSegID(); int index = Polymers.indexOf(new Polymer(chainID, segID)); /** * See if the polymer already exists. */ if (index != -1) { Polymer c = (Polymer) Polymers.get(index); setFinalized(false); return c.addMSNode(residue); } else { Polymer newc = new Polymer(chainID, segID); getAtomNode().add(newc); setFinalized(false); return newc.addMSNode(residue); } } else if (o instanceof Polymer) { Polymer c = (Polymer) o; int index = Polymers.indexOf(c); if (index == -1) { getAtomNode().add(c); setFinalized(false); return c; } else { return (Polymer) Polymers.get(index); } } else if (o instanceof Molecule) { Molecule m = (Molecule) o; if (m.getAtomNode().getChildCount() == 1) { ions.add(m); return m; } else if (Utilities.isWaterOxygen((Atom) m.getAtomNode().getChildAt(0))) { water.add(m); return m; } else { molecules.add(m); return m; } } else { String message = "Programming error in MolecularAssembly addNode"; logger.log(Level.SEVERE, message); return o; } } /** * <p> * center</p> */ public void center() { double center[] = getMultiScaleCenter(false); offset = new Vector3d(center); if (vrml != null) { vrmlTd.set(offset); vrmlTG.setTransform(vrmlTd); } offset.negate(); originToRotV3D.set(offset); originToRotT3D.setTranslation(originToRotV3D); originToRot.setTransform(originToRotT3D); rotToCOMT3D.setIdentity(); rotToCOM.setTransform(rotToCOMT3D); offset.negate(); rotateAbout(offset); originToRotT3D.get(offset); } /** * <p> * centerAt</p> * * @param d an array of double. */ public void centerAt(double[] d) { double[] Rc = { 0, 0, 0 }; double[] c = new double[3]; ListIterator li; int i, num = getAtomList().size(); for (li = getAtomList().listIterator(); li.hasNext();) { ((Atom) li.next()).getXYZ(a); Rc[0] += a[0]; Rc[1] += a[1]; Rc[2] += a[2]; } for (i = 0; i < 3; i++) { Rc[i] /= num; } VectorMath.diff(d, Rc, c); for (li = getAtomList().listIterator(); li.hasNext();) { ((Atom) li.next()).move(c); } } /** * <p> * centerView</p> * * @param rot a boolean. * @param trans a boolean. */ public void centerView(boolean rot, boolean trans) { originToRot.getTransform(originToRotT3D); if (rot) { Matrix3d m3d = new Matrix3d(); m3d.setIdentity(); originToRotT3D.setRotation(m3d); // rotToCOMT3D.setRotation(m3d); } if (trans) { originToRotV3D.set(offset); originToRotT3D.set(originToRotV3D); } originToRot.setTransform(originToRotT3D); // rotToCOM.setTransform(rotToCOMT3D); } /** * <p> * createBox</p> */ public void createBox() { int vertices = 8; LineArray la = new LineArray(4 * vertices, GeometryArray.COORDINATES | GeometryArray.COLOR_4 | GeometryArray.NORMALS); la.setCapability(LineArray.ALLOW_COORDINATE_WRITE); la.setCapability(LineArray.ALLOW_COORDINATE_READ); la.setCapability(LineArray.ALLOW_COLOR_WRITE); la.setCapability(LineArray.ALLOW_COUNT_READ); la.setCapability(LineArray.ALLOW_INTERSECT); la.setCapability(LineArray.ALLOW_FORMAT_READ); // Create a normal // for (ListIterator li = bondlist.listIterator(); li.hasNext(); ){ // la.setCoordinate(i, a1); // la.setColor(i, col); // la.setNormal(i++, a1); // } ColoringAttributes cola = new ColoringAttributes(new Color3f(), ColoringAttributes.SHADE_GOURAUD); Appearance app = new Appearance(); lineAttributes = new LineAttributes(); lineAttributes.setLineWidth(RendererCache.bondwidth); lineAttributes.setCapability(LineAttributes.ALLOW_WIDTH_WRITE); lineAttributes.setLineAntialiasingEnable(true); app.setLineAttributes(lineAttributes); app.setCapability(Appearance.ALLOW_LINE_ATTRIBUTES_READ); app.setCapability(Appearance.ALLOW_LINE_ATTRIBUTES_WRITE); RenderingAttributes ra = new RenderingAttributes(); ra.setAlphaTestValue(0.1f); ra.setAlphaTestFunction(RenderingAttributes.GREATER); ra.setDepthBufferEnable(true); ra.setDepthBufferWriteEnable(true); app.setRenderingAttributes(ra); app.setColoringAttributes(cola); Shape3D wireframe = new Shape3D(la, app); // PickTool.setCapabilities(wire, PickTool.INTERSECT_COORD); wireframe.setUserData(this); wireframe.setBounds(new BoundingSphere(new Point3d(0, 0, 0), 10.0)); try { wireframe.setBoundsAutoCompute(false); } catch (Exception e) { e.printStackTrace(); } wireframe.setCapability(Shape3D.ALLOW_GEOMETRY_READ); wireframe.setCapability(Shape3D.ALLOW_APPEARANCE_READ); // return wire; } /** * The MolecularAssembly BranchGroup has two TransformGroups between it and * the "base" node where geometry is attached. If the point between the two * transformations is where user rotation occurs. For example, if rotating * about the center of mass of the system, the RotToCOM transformation will * be an identity transformation (ie. none). If rotation is about some atom * or group of atoms within the system, then the RotToCOM transformation * will be a translation from that point to the COM. * * @param zero boolean * @return BranchGroup */ public BranchGroup createScene(boolean zero) { originToRotT3D = new Transform3D(); originToRotV3D = new Vector3d(); originToRot = new TransformGroup(originToRotT3D); branchGroup = new BranchGroup(); rotToCOM = new TransformGroup(); rotToCOMT3D = new Transform3D(); rotToCOMV3D = new Vector3d(); // Set capabilities needed for picking and moving the MolecularAssembly branchGroup.setCapability(BranchGroup.ALLOW_DETACH); originToRot.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE); originToRot.setCapability(TransformGroup.ALLOW_TRANSFORM_READ); originToRot.setCapability(TransformGroup.ENABLE_PICK_REPORTING); rotToCOM.setCapability(TransformGroup.ALLOW_TRANSFORM_READ); rotToCOM.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE); // Put the MolecularAssembly in the middle of the scene if (zero) { originToRotV3D.set(0.0, 0.0, 0.0); originToRotT3D.set(originToRotV3D); originToRot.setTransform(originToRotT3D); } wire = renderWire(); switchGroup = new Switch(Switch.CHILD_NONE); switchGroup.setCapability(Switch.ALLOW_SWITCH_WRITE); base = new BranchGroup(); base.setCapability(BranchGroup.ALLOW_CHILDREN_EXTEND); base.setCapability(BranchGroup.ALLOW_CHILDREN_WRITE); childNodes = new BranchGroup(); childNodes.setCapability(BranchGroup.ALLOW_DETACH); childNodes.setCapability(BranchGroup.ALLOW_CHILDREN_EXTEND); childNodes.setCapability(BranchGroup.ALLOW_CHILDREN_WRITE); switchGroup.addChild(base); if (wire != null) { base.addChild(wire); } vrml = loadVRML(); if (vrml != null) { vrmlTG = new TransformGroup(); vrmlTd = new Transform3D(); vrmlTG.setTransform(vrmlTd); vrmlTG.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE); vrmlTG.addChild(vrml); switchGroup.addChild(vrmlTG); setView(RendererCache.ViewModel.INVISIBLE, null); } switchGroup.setWhichChild(Switch.CHILD_ALL); rotToCOM.addChild(switchGroup); originToRot.addChild(rotToCOM); branchGroup.addChild(originToRot); branchGroup.compile(); return branchGroup; } /** * {@inheritDoc} */ @Override public boolean destroy() { try { potentialEnergy.destroy(); } catch (Exception ex) { logger.warning(String.format(" Exception in shutting down force field " + "energy parallel teams: %s", ex.toString())); } detach(); return super.destroy(); } /** * <p> * detach</p> */ public void detach() { synchronized (this) { if (branchGroup != null && branchGroup.isLive()) { branchGroup.detach(); } } } /** * {@inheritDoc} */ @Override public void finalize(boolean finalizeGroups, ForceField forceField) { setFinalized(false); if (finalizeGroups) { bondTime = 0; angleTime = 0; stretchBendTime = 0; ureyBradleyTime = 0; outOfPlaneBendTime = 0; torsionTime = 0; piOrbitalTorsionTime = 0; torsionTorsionTime = 0; ArrayList Polymers = getAtomNodeList(); for (ListIterator li = Polymers.listIterator(); li.hasNext();) { MSGroup group = (MSGroup) li.next(); if (logger.isLoggable(Level.FINE)) { logger.fine(" Finalizing bonded terms for polymer " + group.toString()); } try { group.finalize(true, forceField); } catch (Exception e) { String message = "Fatal exception finalizing " + group.toString(); logger.log(Level.SEVERE, message, e); System.exit(-1); } if (logger.isLoggable(Level.FINE)) { Runtime runtime = Runtime.getRuntime(); long occupiedMemory = runtime.totalMemory() - runtime.freeMemory(); long MB = 1024 * 1024; logger.fine("\n In-Use Memory (Mb): " + occupiedMemory / MB + "\n Free Memory (Mb): " + runtime.freeMemory() / MB + "\n Total Memory (Mb): " + runtime.totalMemory() / MB); } } for (MSNode m : molecules.getChildList()) { Molecule molecule = (Molecule) m; molecule.finalize(true, forceField); } for (MSNode m : water.getChildList()) { Molecule molecule = (Molecule) m; molecule.finalize(true, forceField); } for (MSNode m : ions.getChildList()) { Molecule molecule = (Molecule) m; molecule.finalize(true, forceField); } if (logger.isLoggable(Level.FINE)) { StringBuilder sb = new StringBuilder("\n Time to create bonded energy terms\n\n"); sb.append(String.format(" Bond Streching %10.3f\n", bondTime * 1.0e-9)); sb.append(String.format(" Angle Bending %10.3f\n", angleTime * 1.0e-9)); sb.append(String.format(" Stretch-Bend %10.3f\n", stretchBendTime * 1.0e-9)); sb.append(String.format(" Urey-Bradley %10.3f\n", ureyBradleyTime * 1.0e-9)); sb.append(String.format(" Out-of-Plane Bend %10.3f\n", outOfPlaneBendTime * 1.0e-9)); sb.append(String.format(" Torsionanl Angle %10.3f\n", torsionTime * 1.0e-9)); sb.append(String.format(" Pi-Orbital Torsion %10.3f\n", piOrbitalTorsionTime * 1.0e-9)); sb.append(String.format(" Torsion-Torsion %10.3f\n", torsionTorsionTime * 1.0e-9)); logger.fine(sb.toString()); } } if (!java.awt.GraphicsEnvironment.isHeadless()) { createScene(!finalizeGroups); center(); } removeLeaves(); setFinalized(true); } /** * <p> * findAtom</p> * * @param atom a {@link ffx.potential.bonded.Atom} object. * @return a {@link ffx.potential.bonded.Atom} object. */ public Atom findAtom(Atom atom) { if (!atom.isHetero() || atom.isModRes()) { Polymer polymer = getPolymer(atom.getChainID(), atom.getSegID(), false); if (polymer != null) { Residue res = polymer.getResidue(atom.getResidueName(), atom.getResidueNumber(), false); if (res != null) { MSNode node = res.getAtomNode(); Atom root = (Atom) node.contains(atom); return root; } } return null; } else { ArrayList<Molecule> list = getMolecules(); for (MSNode node : list) { Molecule m = (Molecule) node; if (m.getSegID().equalsIgnoreCase(atom.getSegID()) && m.getResidueName().equalsIgnoreCase(atom.getResidueName()) && m.getResidueNumber() == atom.getResidueNumber()) { Atom root = (Atom) node.contains(atom); return root; } } ArrayList<MSNode> ionList = getIons(); for (MSNode node : ionList) { Molecule m = (Molecule) node; if (m.getSegID().equalsIgnoreCase(atom.getSegID()) && m.getResidueName().equalsIgnoreCase(atom.getResidueName()) && m.getResidueNumber() == atom.getResidueNumber()) { Atom root = (Atom) node.contains(atom); return root; } } ArrayList<MSNode> waterList = getWaters(); for (MSNode node : waterList) { Molecule m = (Molecule) node; if (m.getSegID().equalsIgnoreCase(atom.getSegID()) && m.getResidueName().equalsIgnoreCase(atom.getResidueName()) && m.getResidueNumber() == atom.getResidueNumber()) { Atom root = (Atom) node.contains(atom); return root; } } return null; } } /** * This method assigns a unique integer to every molecule in the * MolecularAssembly beginning at 0. An integer array with these values for * each atom is returned. * * @return an array of molecule numbers for each atom. */ public int[] getMoleculeNumbers() { int moleculeNumber[] = new int[getAtomList().size()]; int current = 0; // Loop over polymers together Polymer[] polymers = getChains(); if (polymers != null && polymers.length > 0) { for (Polymer polymer : polymers) { List<Atom> atomList = polymer.getAtomList(); for (Atom atom : atomList) { moleculeNumber[atom.xyzIndex - 1] = current; } current++; } } // Loop over each molecule for (MSNode molecule : molecules.getChildList()) { List<Atom> atomList = molecule.getAtomList(); for (Atom atom : atomList) { moleculeNumber[atom.xyzIndex - 1] = current; atom.setMoleculeNumber(current); } current++; } // Loop over each water for (MSNode wat : water.getChildList()) { List<Atom> atomList = wat.getAtomList(); for (Atom atom : atomList) { moleculeNumber[atom.xyzIndex - 1] = current; } current++; } // Loop over each ion for (MSNode ion : ions.getChildList()) { List<Atom> atomList = ion.getAtomList(); for (Atom atom : atomList) { moleculeNumber[atom.xyzIndex - 1] = current; } current++; } return moleculeNumber; } /** * <p> * getAltLocations</p> * * @return an array of {@link java.lang.String} objects. */ public String[] getAltLocations() { if (altLoc == null || altLoc.size() == 0) { return null; } String[] names = new String[altLoc.size()]; int i = 0; for (String s : altLoc) { names[i++] = s; } return names; } /** * <p> * getAtomFromWireVertex</p> * * @param i a int. * @return a {@link ffx.potential.bonded.Atom} object. */ public Atom getAtomFromWireVertex(int i) { if (atomLookUp != null && atomLookUp.length > i) { return atomLookUp[i]; } return null; } /** * <p> * getAtomArray</p> * * @return an array of {@link ffx.potential.bonded.Atom} objects. */ public Atom[] getAtomArray() { ArrayList<Atom> atoms = getAtomList(); Atom[] atomArray = atoms.toArray(new Atom[atoms.size()]); Arrays.sort(atomArray); for (int i = 0; i < atoms.size(); i++) { atomArray[i].setXYZIndex(i + 1); } return atomArray; } /** * <p> * getActiveAtomArray</p> * * @return an array of active {@link ffx.potential.bonded.Atom} objects. */ public Atom[] getActiveAtomArray() { ArrayList<Atom> atoms = getAtomList(); ArrayList<Atom> activeAtoms = new ArrayList<>(); for (Atom a : atoms) { if (a.isActive()) { activeAtoms.add(a); } } Atom[] atomArray = activeAtoms.toArray(new Atom[activeAtoms.size()]); Arrays.sort(atomArray); return atomArray; } /** * <p> * getBackBoneAtoms</p> * * @return a {@link java.util.ArrayList} object. */ public ArrayList<Atom> getBackBoneAtoms() { ArrayList<Atom> backbone = new ArrayList<Atom>(); List<Residue> residues = getResidueList(); for (Residue residue : residues) { backbone.addAll(residue.getBackboneAtoms()); } /*Atom ca = new Atom("CA"); ArrayList<ROLS> atoms = this.getList(Atom.class, new ArrayList<ROLS>()); for (ROLS m : atoms) { Atom atom = (Atom) m; if (atom.equals(ca)) { backbone.add(atom); // else if (a.equals(new Atom("C"))) backbone.add(a); // else if (a.equals(new Atom("N"))) backbone.add(a); } }*/ return backbone; } /** * <p> * Getter for the field <code>branchGroup</code>.</p> * * @return a {@link javax.media.j3d.BranchGroup} object. */ public BranchGroup getBranchGroup() { return branchGroup; } /** * <p> * getChain</p> * * @param name a {@link java.lang.String} object. * @return a {@link ffx.potential.bonded.Polymer} object. */ public Polymer getChain(String name) { for (ListIterator li = getAtomNodeList().listIterator(); li.hasNext();) { MSNode node = (MSNode) li.next(); if (node instanceof Polymer) { String chainName = node.getName(); if (chainName.equalsIgnoreCase(name)) { return (Polymer) node; } } } return null; } /** * <p> * getChainNames</p> * * @return an array of {@link java.lang.String} objects. */ public String[] getChainNames() { ArrayList<String> temp = new ArrayList<String>(); for (ListIterator li = getAtomNodeList().listIterator(); li.hasNext();) { MSNode node = (MSNode) li.next(); if (node instanceof Polymer) { temp.add(((Polymer) node).getName()); } } if (temp.size() == 0) { return null; } String[] names = new String[temp.size()]; for (int i = 0; i < temp.size(); i++) { names[i] = temp.get(i); } return names; } /** * <p> * getChains</p> * * @return an array of {@link ffx.potential.bonded.Polymer} objects. */ public Polymer[] getChains() { ArrayList<Polymer> polymers = new ArrayList<Polymer>(); for (ListIterator li = getAtomNodeList().listIterator(); li.hasNext();) { MSNode node = (MSNode) li.next(); if (node instanceof Polymer) { polymers.add((Polymer) node); } } if (polymers.size() == 0) { return null; } return polymers.toArray(new Polymer[polymers.size()]); } /** * <p> * Getter for the field <code>currentCycle</code>.</p> * * @return a int. */ public int getCurrentCycle() { return currentCycle; } /** * <p> * Getter for the field <code>cycles</code>.</p> * * @return a int. */ public int getCycles() { return cycles; } /** * {@inheritDoc} */ @Override public double getExtent() { double[] Rc = { 0, 0, 0 }; int num = getAtomList().size(); for (ListIterator li = getAtomList().listIterator(); li.hasNext();) { ((Atom) li.next()).getXYZ(a); Rc[0] += a[0]; Rc[1] += a[1]; Rc[2] += a[2]; } for (int i = 0; i < 3; i++) { Rc[i] /= num; } double r, d = 0; double[] xyz = new double[3]; for (ListIterator li = getAtomList().listIterator(); li.hasNext();) { ((Atom) li.next()).getXYZ(xyz); VectorMath.diff(xyz, Rc, xyz); r = VectorMath.r(xyz); if (d < r) { d = r; } } return d; } /** * <p> * Getter for the field <code>file</code>.</p> * * @return a {@link java.io.File} object. */ public File getFile() { return file; } /** * <p> * Getter for the field <code>offset</code>.</p> * * @return a {@link javax.vecmath.Vector3d} object. */ public Vector3d getOffset() { if (offset == null) { offset = new Vector3d(0.0, 0.0, 0.0); } return offset; } /** * <p> * Getter for the field <code>originToRot</code>.</p> * * @return a {@link javax.media.j3d.TransformGroup} object. */ public TransformGroup getOriginToRot() { return originToRot; } public CompositeConfiguration getProperties() { return properties == null ? forceField.getProperties() : properties; } /** * <p> * getPolymer</p> * * @param chainID a {@link java.lang.Character} object. * @param segID a {@link java.lang.String} object. * @param create a boolean. * @return a {@link ffx.potential.bonded.Polymer} object. */ public Polymer getPolymer(Character chainID, String segID, boolean create) { for (ListIterator li = getAtomNodeList().listIterator(); li.hasNext();) { MSNode node = (MSNode) li.next(); if (node instanceof Polymer) { Polymer polymer = (Polymer) node; if (polymer.getName().equals(segID) && polymer.getChainID().equals(chainID)) { return (Polymer) node; } } } if (create) { Polymer polymer = new Polymer(chainID, segID, true); addMSNode(polymer); return polymer; } return null; } private Atom getResidue(Atom atom, boolean create) { return getResidue(atom, create, Residue.ResidueType.UNK); } private Atom getResidue(Atom atom, boolean create, Residue.ResidueType defaultRT) { Character chainID = atom.getChainID(); String resName = atom.getResidueName(); int resNum = atom.getResidueNumber(); String segID = atom.getSegID(); // Find/Create the chain Polymer polymer = getPolymer(chainID, segID, create); if (polymer == null) { return null; } Residue res = polymer.getResidue(resName, resNum, create, defaultRT); if (create && res != null) { return (Atom) res.addMSNode(atom); } return null; } /** * <p> * Getter for the field <code>ions</code>.</p> * * @return a {@link java.util.ArrayList} object. */ public ArrayList<MSNode> getIons() { return ions.getChildList(); } /** * <p> * Getter for the field <code>molecules</code>.</p> * * @return a {@link java.util.ArrayList} object. */ public ArrayList<Molecule> getMolecules() { ArrayList<Molecule> ret = new ArrayList<Molecule>(); for (MSNode node : molecules.getChildList()) { ret.add((Molecule) node); } return ret; } /** * <p> * getWaters</p> * * @return a {@link java.util.ArrayList} object. */ public ArrayList<MSNode> getWaters() { return water.getChildList(); } /** * <p> * deleteMolecule</p> * * @param molecule a {@link ffx.potential.bonded.Molecule} object. */ public void deleteMolecule(Molecule molecule) { ArrayList<MSNode> list = ions.getChildList(); for (MSNode node : list) { Molecule m = (Molecule) node; if (molecule == m) { ions.remove(m); return; } } list = water.getChildList(); for (MSNode node : list) { Molecule m = (Molecule) node; if (molecule == m) { water.remove(m); return; } } list = molecules.getChildList(); for (MSNode node : list) { Molecule m = (Molecule) node; if (molecule == m) { molecules.remove(m); return; } } } private Atom getMolecule(Atom atom, boolean create) { String resName = atom.getResidueName(); int resNum = atom.getResidueNumber(); Character chainID = atom.getChainID(); String segID = atom.getSegID(); ArrayList<MSNode> list = ions.getChildList(); for (MSNode node : list) { Molecule m = (Molecule) node; if (m.getSegID().equalsIgnoreCase(segID) && m.getResidueName().equalsIgnoreCase(resName) && m.getResidueNumber() == resNum) { return (Atom) m.addMSNode(atom); } } list = water.getChildList(); for (MSNode node : list) { Molecule m = (Molecule) node; if (m.getSegID().equalsIgnoreCase(segID) && m.getResidueName().equalsIgnoreCase(resName) && m.getResidueNumber() == resNum) { return (Atom) m.addMSNode(atom); } } list = molecules.getChildList(); for (MSNode node : list) { Molecule m = (Molecule) node; if (m.getSegID().equalsIgnoreCase(segID) && m.getResidueName().equalsIgnoreCase(resName) && m.getResidueNumber() == resNum) { return (Atom) m.addMSNode(atom); } } if (create) { Molecule m = new Molecule(resName, resNum, chainID, segID); m.addMSNode(atom); if (resName.equalsIgnoreCase("DOD") || resName.equalsIgnoreCase("HOH") || resName.equalsIgnoreCase("WAT")) { water.add(m); // NA, K, MG, MG2, CA, CA2, CL } else if (resName.equalsIgnoreCase("NA") || resName.equalsIgnoreCase("K") || resName.equalsIgnoreCase("MG") || resName.equalsIgnoreCase("MG2") || resName.equalsIgnoreCase("CA") || resName.equalsIgnoreCase("CA2") || resName.equalsIgnoreCase("CL") || resName.equalsIgnoreCase("BR") || resName.equalsIgnoreCase("ZN") || resName.equalsIgnoreCase("ZN2")) { ions.add(m); } else { molecules.add(m); } return atom; } else { return null; } } /** * <p> * getResidueList</p> * * @return a {@link java.util.ArrayList} object. */ public ArrayList<Residue> getResidueList() { ArrayList<Residue> residues = new ArrayList<Residue>(); ListIterator li, lj; MSNode o; Polymer c; for (li = getAtomNodeList().listIterator(); li.hasNext();) { o = (MSNode) li.next(); if (o instanceof Polymer) { c = (Polymer) o; for (lj = c.getAtomNodeList().listIterator(); lj.hasNext();) { o = (MSNode) lj.next(); if (o instanceof Residue) { residues.add((Residue) o); } } } } return residues; } /** * <p> * getNodeList</p> * * @return a {@link java.util.ArrayList} object. */ public ArrayList<MSNode> getNodeList() { ArrayList<MSNode> residues = new ArrayList<MSNode>(); ListIterator li, lj; MSNode o; Polymer c; for (li = getAtomNodeList().listIterator(); li.hasNext();) { o = (MSNode) li.next(); if (o instanceof Polymer) { c = (Polymer) o; for (lj = c.getAtomNodeList().listIterator(); lj.hasNext();) { o = (MSNode) lj.next(); if (o instanceof Residue) { residues.add(o); } } } } ArrayList<MSNode> list = ions.getChildList(); for (MSNode node : list) { residues.add(node); } list = water.getChildList(); for (MSNode node : list) { residues.add(node); } list = molecules.getChildList(); for (MSNode node : list) { residues.add(node); } return residues; } /** * Sums up charge of the system, checking nonstandard residues for * non-unitary charges. * * @param alwaysLog Log non-unitary charge warnings for all nodes * @return System charge */ public double getCharge(boolean alwaysLog) { double totalCharge = 0; for (MSNode node : getNodeList()) { double charge = 0; boolean isNonstandard = false; for (Atom atom : node.getAtomList()) { charge += atom.getMultipoleType().charge; if (atom.isModRes()) { isNonstandard = true; } } if ((alwaysLog || isNonstandard) && (Math.abs(Math.round(charge) - charge) > 1.0E-5)) { logger.warning(String.format(" Node %s has non-unitary charge %12.8f", node.toString(), charge)); } totalCharge += charge; } return totalCharge; } /** * <p> * getTransformGroup</p> * * @return a {@link javax.media.j3d.TransformGroup} object. */ public TransformGroup getTransformGroup() { return originToRot; } /** * <p> * getWireFrame</p> * * @return a {@link javax.media.j3d.Node} object. */ public Node getWireFrame() { return wire; } /** * <p> * isVisible</p> * * @return a boolean. */ public boolean isVisible() { return visible; } /** * <p> * loadVRML</p> * * @return a {@link javax.media.j3d.BranchGroup} object. */ public BranchGroup loadVRML() { try { VrmlLoader loader = new VrmlLoader(); VrmlScene scene = null; if (vrmlFile != null && vrmlFile.exists()) { scene = (VrmlScene) loader.load(vrmlFile.getAbsolutePath()); } else if (vrmlURL != null) { scene = (VrmlScene) loader.load(vrmlURL); } else { return null; } BranchGroup bg = scene.getSceneGroup(); recurseVRML(bg); bg.setCapability(BranchGroup.ALLOW_DETACH); bg.setCapability(BranchGroup.ALLOW_BOUNDS_READ); bg.compile(); return bg; } catch (Exception e) { String message = "Fatal exception loading VRML.\n"; logger.log(Level.SEVERE, message, e); System.exit(-1); return null; } } /** * <p> * moveCenter</p> * * @param d an array of double. */ public void moveCenter(double[] d) { for (ListIterator li = getAtomList().listIterator(); li.hasNext();) { ((Atom) li.next()).move(d); } } private void recurseVRML(Node node) { if (node instanceof Shape3D) { Shape3D s3d = (Shape3D) node; PickTool.setCapabilities(s3d, PickTool.INTERSECT_COORD); return; } else if (node instanceof SharedGroup) { SharedGroup sg = (SharedGroup) node; for (Enumeration e = sg.getAllChildren(); e.hasMoreElements();) { recurseVRML((Node) e.nextElement()); } return; } else if (node instanceof BranchGroup) { BranchGroup bg = (BranchGroup) node; for (Enumeration e = bg.getAllChildren(); e.hasMoreElements();) { recurseVRML((Node) e.nextElement()); } return; } else if (node instanceof TransformGroup) { TransformGroup vrmlTG1 = (TransformGroup) node; for (Enumeration e = vrmlTG1.getAllChildren(); e.hasMoreElements();) { node = (Node) e.nextElement(); recurseVRML(node); } return; } else if (node instanceof Link) { Link link = (Link) node; recurseVRML(link.getSharedGroup()); return; } else if (node instanceof Group) { Group group = (Group) node; for (Enumeration e = group.getAllChildren(); e.hasMoreElements();) { Node n = (Node) e.nextElement(); recurseVRML(n); } } else { return; } } /** * {@inheritDoc} */ @Override protected void removeLeaves() { super.removeLeaves(); MSNode macroNode = getAtomNode(); if (macroNode != null) { if (macroNode.getChildCount() > 0) { getAtomNode().setName("Macromolecules " + "(" + macroNode.getChildCount() + ")"); } else if (macroNode.getParent() == this) { remove(macroNode); } } if (molecules.getChildCount() == 0) { remove(molecules); } else { molecules.setName("Hetero Molecules " + "(" + molecules.getChildCount() + ")"); } if (ions.getChildCount() == 0) { remove(ions); } else { ions.setName("Ions " + "(" + ions.getChildCount() + ")"); } if (water.getChildCount() == 0) { remove(water); } else { water.setName("Water " + "(" + water.getChildCount() + ")"); } } private Shape3D renderWire() { ArrayList<ROLS> bonds = getBondList(); int numbonds = bonds.size(); if (numbonds < 1) { return null; } Vector3d bondmidpoint = new Vector3d(); double[] mid = { 0, 0, 0 }; Vector3d v1 = new Vector3d(); Vector3d v2 = new Vector3d(); float[] a1 = { 0, 0, 0 }; float[] a2 = { 0, 0, 0 }; float[] col = new float[4]; Bond bond; Atom atom1, atom2; LineArray la = new LineArray(4 * numbonds, GeometryArray.COORDINATES | GeometryArray.COLOR_4 | GeometryArray.NORMALS); la.setCapability(LineArray.ALLOW_COORDINATE_WRITE); la.setCapability(LineArray.ALLOW_COORDINATE_READ); la.setCapability(LineArray.ALLOW_COLOR_WRITE); la.setCapability(LineArray.ALLOW_COUNT_READ); la.setCapability(LineArray.ALLOW_INTERSECT); la.setCapability(LineArray.ALLOW_FORMAT_READ); atomLookUp = new Atom[4 * numbonds]; int i = 0; col[3] = 0.9f; for (ListIterator li = bonds.listIterator(); li.hasNext();) { bond = (Bond) li.next(); bond.setWire(la, i); atom1 = bond.getAtom(0); atom2 = bond.getAtom(1); atom1.getV3D(v1); atom2.getV3D(v2); a1[0] = (float) v1.x; a1[1] = (float) v1.y; a1[2] = (float) v1.z; a2[0] = (float) v2.x; a2[1] = (float) v2.y; a2[2] = (float) v2.z; // Find the bond center bondmidpoint.add(v1, v2); bondmidpoint.scale(0.5d); bondmidpoint.get(mid); // Atom #1 Atom.AtomColor.get(atom1.getAtomicNumber()).get(col); atomLookUp[i] = atom1; la.setCoordinate(i, a1); la.setColor(i, col); la.setNormal(i, a2); i++; atomLookUp[i] = atom1; la.setCoordinate(i, mid); la.setColor(i, col); la.setNormal(i, a2); i++; // Atom #2 Atom.AtomColor.get(atom2.getAtomicNumber()).get(col); atomLookUp[i] = atom2; la.setCoordinate(i, a2); la.setColor(i, col); la.setNormal(i, a1); i++; atomLookUp[i] = atom2; la.setCoordinate(i, mid); la.setColor(i, col); la.setNormal(i, a1); i++; } ColoringAttributes cola = new ColoringAttributes(new Color3f(), ColoringAttributes.SHADE_GOURAUD); Appearance app = new Appearance(); lineAttributes = new LineAttributes(); lineAttributes.setLineWidth(RendererCache.bondwidth); lineAttributes.setCapability(LineAttributes.ALLOW_WIDTH_WRITE); lineAttributes.setLineAntialiasingEnable(true); app.setLineAttributes(lineAttributes); app.setCapability(Appearance.ALLOW_LINE_ATTRIBUTES_READ); app.setCapability(Appearance.ALLOW_LINE_ATTRIBUTES_WRITE); RenderingAttributes ra = new RenderingAttributes(); ra.setAlphaTestValue(0.1f); ra.setAlphaTestFunction(RenderingAttributes.GREATER); ra.setDepthBufferEnable(true); ra.setDepthBufferWriteEnable(true); app.setRenderingAttributes(ra); app.setColoringAttributes(cola); Shape3D wireframe = new Shape3D(la, app); // PickTool.setCapabilities(wire, PickTool.INTERSECT_COORD); wireframe.setUserData(this); wireframe.setBounds(new BoundingSphere(new Point3d(0, 0, 0), 1000.0)); try { wireframe.setBoundsAutoCompute(false); } catch (Exception e) { e.printStackTrace(); } wireframe.setCapability(Shape3D.ALLOW_GEOMETRY_READ); wireframe.setCapability(Shape3D.ALLOW_APPEARANCE_READ); wireframe.setCapability(Shape3D.ALLOW_LOCAL_TO_VWORLD_READ); return wireframe; } /** * Rotate about a point in given in the System's Local Coordinates * * @param v Vector3d */ public void rotateAbout(Vector3d v) { Vector3d newRotPoint = new Vector3d(v); originToRot.getTransform(originToRotT3D); originToRotT3D.get(originToRotV3D); originToRotT3D.setTranslation(new Vector3d(0, 0, 0)); rotToCOM.getTransform(rotToCOMT3D); rotToCOMT3D.get(rotToCOMV3D); newRotPoint.add(rotToCOMV3D); originToRotT3D.transform(newRotPoint); newRotPoint.add(originToRotV3D); originToRotT3D.setTranslation(newRotPoint); rotToCOMV3D.set(v); rotToCOMV3D.negate(); rotToCOMT3D.setTranslation(rotToCOMV3D); originToRot.setTransform(originToRotT3D); rotToCOM.setTransform(rotToCOMT3D); } /** * <p> * sceneGraphChange</p> * * @param newShapes a {@link java.util.List} object. */ public void sceneGraphChange(List<BranchGroup> newShapes) { if (newShapes == null) { newShapes = myNewShapes; } if (newShapes.isEmpty()) { return; } boolean reCompile = false; // Check for nodes (new and/or recycled) being added to this // MolecularAssembly for (ListIterator<BranchGroup> li = newShapes.listIterator(); li.hasNext();) { BranchGroup group = li.next(); li.remove(); // This is code for cycling between two MolecularAssemblies if (group.getUserData() != null) { logger.info(group.toString() + " " + group.getUserData()); /* * Object userData = group.getUserData(); if (userData!=this) { * // The appearance has already been set during a recursive * call to setView, // although we need to turn back on * Pickablility. TransformGroup tg = (TransformGroup) * group.getChild(0); Shape3D shape = (Shape3D) tg.getChild(0); * shape.setPickable(true); group.setUserData(this); if * (!reCompile) { if (childNodes.isLive()) { * childNodes.detach(); } reCompile = true; } * childNodes.moveTo(group); */ } else { // This is a new group since it has no userData. // We can not query for the identity of its parent later, so // we will store it as a userData reference. group.setUserData(this); if (!reCompile) { if (childNodes.isLive()) { childNodes.detach(); } reCompile = true; } childNodes.addChild(group); } } if (reCompile) { childNodes.compile(); base.addChild(childNodes); } } /** * {@inheritDoc} */ @Override public void setColor(RendererCache.ColorModel newColorModel, Color3f color, Material mat) { for (ListIterator li = getAtomNodeList().listIterator(); li.hasNext();) { MSGroup group = (MSGroup) li.next(); group.setColor(newColorModel, color, mat); } for (MSNode m : molecules.getChildList()) { m.setColor(newColorModel, color, mat); } for (MSNode m : water.getChildList()) { m.setColor(newColorModel, color, mat); } for (MSNode m : ions.getChildList()) { m.setColor(newColorModel, color, mat); } } /** * <p> * Setter for the field <code>currentCycle</code>.</p> * * @param c a int. */ public void setCurrentCycle(int c) { if (c <= cycles && c > 0) { currentCycle = c; for (ListIterator li = getAtomList().listIterator(); li.hasNext();) { ((Atom) li.next()).setCurrentCycle(currentCycle); } } } /** * <p> * Setter for the field <code>cycles</code>.</p> * * @param c a int. */ public void setCycles(int c) { cycles = c; } /** * <p> * Setter for the field <code>file</code>.</p> * * @param f a {@link java.io.File} object. */ public void setFile(File f) { if (f == null) { return; } file = f; } /** * <p> * Setter for the field <code>offset</code>.</p> * * @param o a {@link javax.vecmath.Vector3d} object. */ public void setOffset(Vector3d o) { offset = o; } /** * {@inheritDoc} */ @Override public void setView(RendererCache.ViewModel newViewModel, List<BranchGroup> newShapes) { // Just Detach the whole system branch group if (newViewModel == RendererCache.ViewModel.DESTROY) { if (switchGroup != null) { switchGroup.setWhichChild(Switch.CHILD_NONE); } visible = false; } else if (newViewModel == RendererCache.ViewModel.SHOWVRML) { switchGroup.setWhichChild(Switch.CHILD_ALL); } else if (newViewModel == RendererCache.ViewModel.HIDEVRML) { switchGroup.setWhichChild(0); } else { setWireWidth(RendererCache.bondwidth); if (newViewModel == RendererCache.ViewModel.DETAIL && childNodes.isLive()) { childNodes.detach(); } /** * We'll collect new Scenegraph Shapes in our newShapeNode This is * to avoid the case where setView is called from the root node and * all new shapes for every MolecularAssembly would then be put into * the same ArrayList. */ super.setView(newViewModel, myNewShapes); ArrayList<ROLS> moleculeList = getList(Molecule.class, new ArrayList<ROLS>()); for (ROLS m : moleculeList) { m.setView(newViewModel, myNewShapes); } for (MSNode m : molecules.getChildList()) { m.setView(newViewModel, myNewShapes); } for (MSNode m : water.getChildList()) { m.setView(newViewModel, myNewShapes); } for (MSNode m : ions.getChildList()) { m.setView(newViewModel, myNewShapes); } if (newViewModel == RendererCache.ViewModel.INVISIBLE) { switchGroup.setWhichChild(0); } if (newViewModel == RendererCache.ViewModel.DETAIL) { childNodes.compile(); base.addChild(childNodes); } } } /** * <p> * setVRML</p> * * @param v a {@link javax.media.j3d.BranchGroup} object. */ public void setVRML(BranchGroup v) { vrmlURL = null; vrmlFile = null; vrml = v; } /** * <p> * setVRML</p> * * @param file a {@link java.io.File} object. */ public void setVRML(File file) { vrmlFile = file; vrmlURL = null; } /** * <p> * setVRML</p> * * @param url a {@link java.net.URL} object. */ public void setVRML(URL url) { vrmlURL = url; vrmlFile = null; } /** * <p> * setWireWidth</p> * * @param f a float. */ public void setWireWidth(float f) { if (wire == null) { return; } lineAttributes.setLineWidth(f); } /** * <p> * sidePolymerCOM</p> */ public void sidePolymerCOM() { ArrayList residues = getResidueList(); Residue r; ListIterator li; for (li = residues.listIterator(); li.hasNext();) { r = (Residue) li.next(); r.logSideChainCOM(); } } }