From: <ha...@us...> - 2013-06-30 07:21:46
|
Revision: 18382 http://sourceforge.net/p/jmol/code/18382 Author: hansonr Date: 2013-06-30 07:21:27 +0000 (Sun, 30 Jun 2013) Log Message: ----------- Tensor Javadoc and code clean-up Modified Paths: -------------- trunk/Jmol/src/org/jmol/adapter/readers/cifpdb/PdbReader.java trunk/Jmol/src/org/jmol/modelset/AtomCollection.java trunk/Jmol/src/org/jmol/shapespecial/Ellipsoids.java trunk/Jmol/src/org/jmol/symmetry/UnitCell.java trunk/Jmol/src/org/jmol/util/Tensor.java Modified: trunk/Jmol/src/org/jmol/adapter/readers/cifpdb/PdbReader.java =================================================================== --- trunk/Jmol/src/org/jmol/adapter/readers/cifpdb/PdbReader.java 2013-06-29 23:32:44 UTC (rev 18381) +++ trunk/Jmol/src/org/jmol/adapter/readers/cifpdb/PdbReader.java 2013-06-30 07:21:27 UTC (rev 18382) @@ -59,6 +59,11 @@ * see http://repo.or.cz/w/gromacs.git/blob/HEAD:/src/gmxlib/pdbio.c line 244 * see http://repo.or.cz/w/gromacs.git/blob/HEAD:/src/gmxlib/pdbio.c line 323 * + * TLS Motion Determination: + * + * J Painter & E A Merritt (2006) Acta Cryst. D62, 439-450 + * http://skuld.bmsc.washington.edu/~tlsmd + * * symmetry added by Bob Hanson: * * setFractionalCoordinates() @@ -1602,21 +1607,19 @@ tensorType, ' ').replace(':', ' '); //System.out.println("Tensor data = " + s); tokens = getTokensStr(s); - float[][] tensor = new float[3][3]; - tlsGroup.put("t" + tensorType, tensor); + float[][] data = new float[3][3]; + tlsGroup.put("t" + tensorType, data); for (int i = 0; i < tokens.length; i++) { int ti = tokens[i].charAt(0) - '1'; int tj = tokens[i].charAt(1) - '1'; - tensor[ti][tj] = parseFloatStr(tokens[++i]); + data[ti][tj] = parseFloatStr(tokens[++i]); if (ti < tj) - tensor[tj][ti] = tensor[ti][tj]; + data[tj][ti] = data[ti][tj]; } for (int i = 0; i < 3; i++) for (int j = 0; j < 3; j++) - if (Float.isNaN(tensor[i][j])) { - tlsAddError("invalid tensor: " + Escape.escapeFloatAA(tensor, false)); - - } + if (Float.isNaN(data[i][j])) + tlsAddError("invalid tensor: " + Escape.escapeFloatAA(data, false)); //System.out.println("Tensor t" + tensorType + " = " + Escape.escape(tensor)); if (tensorType == 'S' && ++iGroup == nGroups) { Logger.info(nGroups + " TLS groups read"); @@ -1632,10 +1635,10 @@ } } if (tlsGroups != null) { - Hashtable<String, Object> groups = new Hashtable<String, Object>(); - groups.put("groupCount", Integer.valueOf(nGroups)); - groups.put("groups", tlsGroups); - vTlsModels.addLast(groups); + Hashtable<String, Object> tlsModel = new Hashtable<String, Object>(); + tlsModel.put("groupCount", Integer.valueOf(nGroups)); + tlsModel.put("groups", tlsGroups); + vTlsModels.addLast(tlsModel); } return (nGroups < 1); } @@ -1648,7 +1651,8 @@ } /** - * sets the atom property property_tlsGroup based on TLS group ranges + * Sets the atom property property_tlsGroup based on TLS group ranges + * and adds "TLS" key to model's auxiliaryInfo. * * @param iGroup * @param iModel @@ -1656,6 +1660,26 @@ */ @SuppressWarnings("unchecked") private void setTlsGroups(int iGroup, int iModel, SymmetryInterface symmetry) { + + // TLS.groupCount Integer + // TLS.groups JmolList of Map + // .id String + // .ranges JmolList of Map + // .chains String + // .residues int[2] + // .origin P3 + // .tT float[3][3] + // .tL float[3][3] + // .tS float[3][3] + // + // ultimately, each atom gets an associated TLS-U and TLS-R org.jmol.util.Tensor + // that can be visualized using + // + // ellipsoid set "TLS-R" + // ellipsoids ON + // + // + Logger.info("TLS model " + (iModel + 1) + " set " + (iGroup + 1)); Map<String, Object> tlsGroupInfo = vTlsModels.get(iGroup); JmolList<Map<String, Object>> groups = ( JmolList<Map<String, Object>>) tlsGroupInfo Modified: trunk/Jmol/src/org/jmol/modelset/AtomCollection.java =================================================================== --- trunk/Jmol/src/org/jmol/modelset/AtomCollection.java 2013-06-29 23:32:44 UTC (rev 18381) +++ trunk/Jmol/src/org/jmol/modelset/AtomCollection.java 2013-06-30 07:21:27 UTC (rev 18382) @@ -168,7 +168,6 @@ return atomTypes; } - public float[] getPartialCharges() { return partialCharges; } @@ -266,20 +265,13 @@ t.atomIndex2 = -1; t.modelIndex = atoms[atomIndex].modelIndex; addTensor(t, t.type); - int pt = "charge temp TLS-R TLS-U".indexOf(t.type + " "); - // 0 7 14 21 - // "1" is assigned for Born Effective Charges and temperature - // "2" is TLS-R - // "3" is TLS-U - // and no more of that! - if (pt >= 0) { - addTensor(t, t.altType = "" + (pt >= 14 ? pt / 7: 1)); - } + if (t.altType != null) + addTensor(t, t.altType); } } public JmolList<Tensor> getAllAtomTensors(String type) { - return atomTensors.get(type); + return atomTensors.get(type.toLowerCase()); } private Tensor[] getTensorList(JmolList<Tensor> list) { @@ -290,7 +282,7 @@ Tensor t = list.get(i); if (t.forThermalEllipsoid) pt = i; - else if (t.type.equals("TLS-U")) + else if (t.iType == Tensor.TYPE_TLS_U) haveTLS = true; } Tensor[] a = new Tensor[(pt >= 0 || !haveTLS ? 0 : 1) + n]; @@ -317,6 +309,7 @@ } private void addTensor(Tensor t, String type) { + type = type.toLowerCase(); JmolList<Tensor> tensors = atomTensors.get(type); if (tensors == null) atomTensors.put(type, tensors = new JmolList<Tensor>()); Modified: trunk/Jmol/src/org/jmol/shapespecial/Ellipsoids.java =================================================================== --- trunk/Jmol/src/org/jmol/shapespecial/Ellipsoids.java 2013-06-29 23:32:44 UTC (rev 18381) +++ trunk/Jmol/src/org/jmol/shapespecial/Ellipsoids.java 2013-06-30 07:21:27 UTC (rev 18382) @@ -194,7 +194,7 @@ } if ("select" == propertyName) { - typeSelected = (String) value; + typeSelected = ((String) value).toLowerCase(); return; } @@ -210,7 +210,7 @@ short colix = C.getColixO(value); byte pid = EnumPalette.pidOf(value); for (Ellipsoid e : atomEllipsoids.values()) - if (e.tensor.type.equals(typeSelected)) { + if (e.tensor.type.equalsIgnoreCase(typeSelected)) { e.colix = getColixI(colix, pid, e.tensor.atomIndex1); e.pid = pid; } @@ -220,7 +220,7 @@ if ("translucency" == propertyName) { boolean isTranslucent = (value.equals("translucent")); for (Ellipsoid e : atomEllipsoids.values()) - if (e.tensor.type.equals(typeSelected)) + if (e.tensor.type.equalsIgnoreCase(typeSelected)) e.colix = C.getColixTranslucent3(e.colix, isTranslucent, translucentLevel); return; Modified: trunk/Jmol/src/org/jmol/symmetry/UnitCell.java =================================================================== --- trunk/Jmol/src/org/jmol/symmetry/UnitCell.java 2013-06-29 23:32:44 UTC (rev 18381) +++ trunk/Jmol/src/org/jmol/symmetry/UnitCell.java 2013-06-30 07:21:27 UTC (rev 18382) @@ -263,8 +263,10 @@ * The coefficients bij (i,j = 1,2,3) of the various types are defined with * the following constant settings. * - * Type 0: Base = e, c = 2, D = 1 Type 1: Base = e, c = 1, D = l Type 2: - * Base = 2, c = 2, D = l Type 3: Base = 2, c = 1, D = l + * Type 0: Base = e, c = 2, D = 1 + * Type 1: Base = e, c = 1, D = l + * Type 2: Base = 2, c = 2, D = l + * Type 3: Base = 2, c = 1, D = l * * Anisotropic temperature factor Types 4, 5, 8, and 9 use the following * formula for the complete temperature factor, in which a1* , a2*, a3* are @@ -276,7 +278,9 @@ * The coefficients Uij (i,j = 1,2,3) of the various types are defined with * the following constant settings. * - * Type 4: C = 2, D = 1/4 Type 5: C = 1, D = 1/4 Type 8: C = 2, D = 2pi2 + * Type 4: C = 2, D = 1/4 + * Type 5: C = 1, D = 1/4 + * Type 8: C = 2, D = 2pi2 * Type 9: C = 1, D = 2pi2 * * Modified: trunk/Jmol/src/org/jmol/util/Tensor.java =================================================================== --- trunk/Jmol/src/org/jmol/util/Tensor.java 2013-06-29 23:32:44 UTC (rev 18381) +++ trunk/Jmol/src/org/jmol/util/Tensor.java 2013-06-30 07:21:27 UTC (rev 18382) @@ -27,55 +27,110 @@ import java.util.Arrays; import java.util.Comparator; +/** + * @author Bob Hanson ha...@st... 6/30/2013 + * + */ public class Tensor { - private static float TEMPERATURE_FACTOR = (float) (Math.sqrt(0.5) / Math.PI); + // factors that give reasonable first views of ellipsoids. + + private static final float TEMPERATURE_FACTOR = (float) (Math.sqrt(0.5) / Math.PI); private static final float MAGNETIC_SUSCEPTIBILITY_FACTOR = 0.01f; + private static final float ELECTRIC_FIELD_GRADIENT_FACTOR = 1f; private static final float BORN_EFFECTIVE_CHARGE_FACTOR = 1f; private static final float INTERACTION_FACTOR = 0.04f; + + private static TensorSort tSort; // used for sorting eigenvector/values - private static TensorSort tSort; + // base data: + + public String type; + public int iType = TYPE_OTHER; + + // type is an identifier that the reader/creator delivers: + // + // temp -- crystallographic displacement parameters + // - "temperature factors"; t.forThermalEllipsoid = true + // - either anisotropic (ADP) or isotropic (IDP) + // iso -- isotropic displacement parameters; from org.jmol.symmetry.UnitCell + // - changed to "temp" after setting t.isIsotropic = true + // ms -- magnetic susceptibility + // isc -- NMR interaction tensors + // - will have both atomIndex1 and atomIndex2 defined when + // - incorporated into a model + // charge -- Born Effective Charge tensor + // TLS-U -- Translation/Libration/Skew tensor (anisotropic) + // TLS-R -- Translation/Libration/Skew tensor (residual) + + private static final String KNOWN_TYPES = ";iso....;temp...;tls-u..;tls-r..;ms.....;efg....;isc....;charge.;"; + private static int getType(String type) { + int pt = KNOWN_TYPES.indexOf(";" + type.toLowerCase() + "."); + return (pt < 0 ? TYPE_OTHER : pt / 8); + } - private double[][] asymmetricTensor; - + // these may be augmented, but the order should be kept the same within this list - public String type; // iso temp ms isc charge TLS-R TLS-U... + public static final int TYPE_OTHER = -1; + public static final int TYPE_ISO = 0; + public static final int TYPE_TEMP = 1; + public static final int TYPE_TLS_U = 2; + public static final int TYPE_TLS_R = 3; + public static final int TYPE_MS = 4; + public static final int TYPE_EFG = 5; + public static final int TYPE_ISC = 6; + public static final int TYPE_CHARGE = 7; + + public double[][] asymTensor; + public double[][] symTensor; + public V3[] eigenVectors; + public float[] eigenValues; + + // derived type-based information, Jmol-centric, for rendering: + public String altType; // "0" "1" "2" - public float typeFactor = 1; + // altType is somewhat of a legacy - just lets you use + + // ellipsoid SET 1 + // ellipsoid SET 2 + // etc... + + public boolean isIsotropic; // just rendered as balls, not special features + public boolean forThermalEllipsoid; + public int eigenSignMask = 7; // signs of eigenvalues; bits 2,1,0 set to 1 if > 0 + private float typeFactor = 1; // an ellipsoid scaling factor depending upon type + + // added only after passing + // the tensor to ModelLoader: + public int modelIndex; public int atomIndex1 = -1; public int atomIndex2 = -1; - public V3[] eigenVectors; // possibly null (isotropic) - public float[] eigenValues; - - public boolean forThermalEllipsoid = true; - public int eigenSignMask = 7; - public boolean isIsotropic; - public static Tensor copyTensor(Tensor t0) { Tensor t = new Tensor(); + t.setType(t0.type); t.eigenValues = t0.eigenValues; t.eigenVectors = t0.eigenVectors; - t.asymmetricTensor = t0.asymmetricTensor; - t.type = t0.type; - t.typeFactor = t0.typeFactor; + t.asymTensor = t0.asymTensor; + t.symTensor = t0.symTensor; + t.eigenSignMask = t0.eigenSignMask; + t.modelIndex = t0.modelIndex; + t.atomIndex1 = t0.atomIndex1; + t.atomIndex2 = t0.atomIndex2; return t; } - - public double[][] getAsymmetricTensor() { - return asymmetricTensor; - } - /** - * all instantiation must go through one of the static getTensor... methods + * private constructor so that all instantiation must go through one + * of the static getTensor... methods to set fields properly. * */ private Tensor() {} /** + * Standard constructor for QM tensors * * @param asymmetricTensor * @param type @@ -127,10 +182,19 @@ float[] values = new float[3]; eigen.fillArrays(vectors, values); Tensor t = newTensorType(vectors, values, type); - t.asymmetricTensor = asymmetricTensor; + t.asymTensor = asymmetricTensor; + t.symTensor = a; return t; } + /** + * Standard constructor for charge and iso + * + * @param eigenVectors + * @param eigenValues + * @param type + * @return Tensor + */ public static Tensor getTensorFromEigenVectors(V3[] eigenVectors, float[] eigenValues, String type) { float[] values = new float[3]; @@ -139,11 +203,15 @@ vectors[i] = V3.newV(eigenVectors[i]); values[i] = eigenValues[i]; } - Tensor t = newTensorType(vectors, values, type); - t.isIsotropic = "iso".equals(type); - return t; + return newTensorType(vectors, values, type); } + /** + * Standard constructor for ellipsoids based on axes + * + * @param axes + * @return Tensor + */ public static Tensor getTensorFromAxes(V3[] axes) { Tensor t = new Tensor(); t.eigenValues = new float[3]; @@ -160,30 +228,76 @@ || Math.abs(t.eigenVectors[2].dot(t.eigenVectors[0])) > 0.0001f) return null; sort(t.eigenVectors, t.eigenValues); - return t; + return t.setType("other"); } - public static Tensor getTensorFromThermalEquation(double[] coef) { + /** + * standard constructor for thermal ellipsoids convention beta + * (see http://www.iucr.org/iucr-top/comm/cnom/adp/finrepone/finrepone.html) + * + * @param coefs + * @return Tensor + */ + public static Tensor getTensorFromThermalEquation(double[] coefs) { Tensor t = new Tensor(); t.eigenValues = new float[3]; t.eigenVectors = new V3[3]; // assumes an ellipsoid centered on 0,0,0 - // called by UnitCell for the initial creation of Object[] ellipsoid + // called by UnitCell for the initial creation from PDB/CIF ADP data double[][] mat = new double[3][3]; - mat[0][0] = coef[0]; //XX - mat[1][1] = coef[1]; //YY - mat[2][2] = coef[2]; //ZZ - mat[0][1] = mat[1][0] = coef[3] / 2; //XY - mat[0][2] = mat[2][0] = coef[4] / 2; //XZ - mat[1][2] = mat[2][1] = coef[5] / 2; //YZ + mat[0][0] = coefs[0]; //XX + mat[1][1] = coefs[1]; //YY + mat[2][2] = coefs[2]; //ZZ + mat[0][1] = mat[1][0] = coefs[3] / 2; //XY + mat[0][2] = mat[2][0] = coefs[4] / 2; //XZ + mat[1][2] = mat[2][1] = coefs[5] / 2; //YZ Eigen.getUnitVectors(mat, t.eigenVectors, t.eigenValues); sort(t.eigenVectors, t.eigenValues); t.typeFactor = TEMPERATURE_FACTOR; - t.type = "temp"; - t.setTypeFactor(); - return t; + return t.setType("temp"); } + /** + * Note that type may be null here to skip type initialization + * and allow later setting of type; this should be used with care. + * + * @param type + * @return "this" for convenience only + */ + public Tensor setType(String type) { + if (this.type == null || type == null) + this.type = type; + if (type != null) + processType(); + return this; + } + + /** + * Returns a factored eigenvalue; thermal ellipsoids use sqrt(abs(eigenvalue)) for + * ellipsoid axes; others use just use abs(eigenvalue); all cases get factored by + * typeFactor + * + * @param i + * @return factored eigenvalue + */ + public float getFactoredValue(int i) { + float f = Math.abs(eigenValues[i]); + return (forThermalEllipsoid ? (float) Math.sqrt(f) : f) * typeFactor; + } + + public void setAtomIndexes(int index1, int index2) { + atomIndex1 = index1; + atomIndex2 = index2; + } + + /** + * common processing of eigenvectors. + * + * @param vectors + * @param values + * @param type + * @return Tensor + */ private static Tensor newTensorType(V3[] vectors, float[] values, String type) { Tensor t = new Tensor(); t.eigenValues = values; @@ -197,62 +311,64 @@ return t; } - private void setTypeFactor() { + /** + * Sets typeFactor, altType, isIsotropic, forThermalEllipsoid; + * type "iso" changed to "temp" here. + * + */ + private void processType() { + forThermalEllipsoid = false; - switch ("iso temp ms isc chargeTLS-UTLS-R".indexOf(type)) { - // 0 5 10 15 20 25 30 - default: // TLS, other - typeFactor = 1; - break; - case 0: // iso + isIsotropic = false; + altType = null; + typeFactor = 1; + + switch (iType = getType(type)) { + case TYPE_ISO: forThermalEllipsoid = true; - typeFactor = 1; + isIsotropic = true; + altType = "1"; + type = "temp"; break; - case 5: // temp + case TYPE_TEMP: forThermalEllipsoid = true; typeFactor = TEMPERATURE_FACTOR; + altType = "1"; break; - case 10: // ms + case TYPE_MS: typeFactor = MAGNETIC_SUSCEPTIBILITY_FACTOR; break; - case 15: // isc + case TYPE_EFG: + typeFactor = ELECTRIC_FIELD_GRADIENT_FACTOR; + break; + case TYPE_ISC: typeFactor = INTERACTION_FACTOR; break; - case 20: // charge + case TYPE_CHARGE: typeFactor = BORN_EFFECTIVE_CHARGE_FACTOR; break; + case TYPE_TLS_R: + altType = "2"; + break; + case TYPE_TLS_U: + altType = "3"; + break; } } - public Tensor setType(String type) { - if (this.type == null || type == null) - this.type = type; - setTypeFactor(); - return this; - } - - public float getFactoredValue(int i) { - float f = Math.abs(eigenValues[i]); - return (forThermalEllipsoid ? (float) Math.sqrt(f) : f) * typeFactor; - } - - public void setAtomIndexes(int index1, int index2) { - atomIndex1 = index1; - atomIndex2 = index2; - } - private static int[] sortOrder = { 1, 0, 2 }; /** - * sorts EigenVectors by + * sorts EigenVectors by * + * |sigma_3 - sigma_iso| >= |sigma_1 - sigma_iso| >= |sigma_2 - sigma_iso| + * * and normalize the eigenVectors * * @param eigenVectors * @param eigenValues */ private static void sort(V3[] eigenVectors, float[] eigenValues) { - // |sigma_3 - sigma_iso| >= |sigma_1 - sigma_iso| >= |sigma_2 - sigma_iso| // first sorted 3 2 1, then 1 and 2 are switched using the sortOrder above. Object[][] o = new Object[][] { new Object[] { eigenVectors[0], Float.valueOf(eigenValues[0]) }, This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |