1 /* $RCSfile$ 2 * $Author: hansonr $ 3 * $Date: 2006-09-11 23:56:13 -0500 (Mon, 11 Sep 2006) $ 4 * $Revision: 5499 $ 5 * 6 * Copyright (C) 2003-2005 Miguel, Jmol Development, www.jmol.org 7 * 8 * Contact: jmol-developers@lists.sf.net 9 * 10 * This library is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU Lesser General Public 12 * License as published by the Free Software Foundation; either 13 * version 2.1 of the License, or (at your option) any later version. 14 * 15 * This library is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 * Lesser General Public License for more details. 19 * 20 * You should have received a copy of the GNU Lesser General Public 21 * License along with this library; if not, write to the Free Software 22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 23 */ 24 25 package org.jmol.adapter.readers.spartan; 26 27 import java.util.Hashtable; 28 import java.util.Map; 29 30 import org.jmol.util.Logger; 31 32 import javajs.util.BC; 33 import javajs.util.PT; 34 import javajs.util.SB; 35 36 /* 37 * Spartan SMOL and .spartan compound document reader and .spartan06 zip files 38 * 39 */ 40 41 public class SpartanSmolReader extends SpartanInputReader { 42 43 private boolean iHaveModelStatement; 44 private boolean isCompoundDocument; 45 private boolean inputOnly; 46 private boolean espCharges; 47 private boolean natCharges; 48 private boolean isInputFirst; 49 private boolean iHaveNewDir; 50 51 @Override initializeReader()52 protected void initializeReader() throws Exception { 53 isCompoundDocument = (rd() 54 .indexOf("Compound Document File Directory") >= 0); 55 inputOnly = checkFilterKey("INPUT"); 56 natCharges = checkFilterKey("NATCHAR"); 57 espCharges = !natCharges && !checkFilterKey("MULLIKEN"); // changed default in Jmol 12.1.41, 12.0.38 58 59 } 60 61 @Override checkLine()62 protected boolean checkLine() throws Exception { 63 // BH Note: I will be the first to say that this coding is way too complicated. 64 // The original design accommodates too many variations. There are 65 // the Spartan for Windows compound document, the MacSpartan directory, and 66 // the Jmol translation of each of those. 67 68 // JMOL_MODEL is a bogus type added by Jmol as a marker only, 69 // added only to the MacSpartan directory format. 70 // That record is placed BEFORE the Input record, while 71 // for the compound document, Input comes before Molecule. 72 73 // MacSpartan: 74 // c:/temp/cyclohexane_movie.spardir/M0001/#JMOL_MODEL M0001 75 // BEGIN Directory Entry c:/temp/cyclohexane_movie.spardir/M0001/input 76 // BEGIN Directory Entry c:/temp/cyclohexane_movie.spardir/M0001/Molecule:asBinaryString 77 // Spartan for Windows; Spartan 14: 78 // BEGIN Directory Entry Input 79 // BEGIN Directory Entry Molecule 80 // 81 int pt = 3; 82 boolean isNewDir = (isCompoundDocument 83 && line.startsWith("NEW Directory M") 84 && !line.startsWith("NEW Directory Molecules")); 85 if (isNewDir) 86 iHaveNewDir = true; 87 boolean isMolecule = (!iHaveNewDir && !isNewDir && isCompoundDocument && line 88 .equals("BEGIN Directory Entry Molecule")); 89 boolean isMacDir = (!isCompoundDocument && (pt = line.indexOf("#JMOL_MODEL")) >= 0); 90 if (isNewDir || isMolecule || isMacDir) { 91 if (modelNumber > 0 && !isInputFirst) 92 applySymmetryAndSetTrajectory(); 93 iHaveModelStatement = true; 94 int modelNo = (isMolecule ? 0 : parseIntAt(line, pt + 12)); 95 modelNumber = (bsModels == null && modelNo != Integer.MIN_VALUE && modelNo != 0 ? modelNo 96 : modelNumber + 1); 97 bondData = ""; 98 if (!doGetModel(modelNumber, null)) { 99 if (isInputFirst) { 100 asc.removeCurrentAtomSet(); 101 discardLinesUntilContains("BEGIN Directory Entry Input"); 102 } else if (isNewDir) { 103 discardLinesUntilContains("NEW Directory M"); 104 } else if (isMolecule) { 105 discardLinesUntilContains("BEGIN Directory Entry M"); 106 } else { 107 discardLinesUntilContains("#JMOL_MODEL"); 108 } 109 checkLastModel(); 110 return false; 111 } 112 if (!isInputFirst) { 113 makeNewAtomSet(); 114 } 115 moData = new Hashtable<String, Object>(); 116 moData.put("isNormalized", Boolean.TRUE); 117 boolean isOK = false; 118 if (modelNo == Integer.MIN_VALUE || titles == null) { 119 modelNo = modelNumber; 120 title = "Model " + modelNo; 121 } else { 122 isOK = true; 123 title = titles.get("Title" + modelNo); 124 title = "Profile " + modelNo + (title == null ? "" : ": " + title); 125 } 126 if (constraints == null && (isOK || !isInputFirst)) 127 asc.setAtomSetName(title); 128 setModelPDB(false); 129 asc.setCurrentAtomSetNumber(modelNo); 130 if (isMolecule) 131 readMyTransform(); 132 return true; 133 } 134 if (iHaveModelStatement && !doProcessLines) 135 return true; 136 if ((line.indexOf("BEGIN") == 0)) { 137 String lcline = line.toLowerCase(); 138 if (lcline.endsWith("input")) { 139 if (!iHaveModelStatement) 140 isInputFirst = true; 141 if (isInputFirst) { 142 makeNewAtomSet(); 143 } 144 bondData = ""; 145 title = readInputRecords(); 146 if (asc.errorMessage != null) { 147 continuing = false; 148 return false; 149 } 150 if (title != null && constraints == null) 151 asc.setAtomSetName(title); 152 setCharges(); 153 if (inputOnly) { 154 continuing = false; 155 return false; 156 } 157 } else if (lcline.endsWith("_output")) { 158 return true; 159 } else if (lcline.endsWith("output")) { 160 readOutput(); 161 return false; 162 } else if (lcline.endsWith("molecule") 163 || lcline.endsWith("molecule:asbinarystring")) { 164 readMyTransform(); 165 return false; 166 } else if (lcline.endsWith("proparc") 167 || lcline.endsWith("propertyarchive")) { 168 readProperties(); 169 return false; 170 } else if (lcline.endsWith("molstate")) { 171 readTransform(); 172 return false; 173 } else if (lcline.endsWith("archive")) { 174 asc.setAtomSetName(readArchive()); 175 return false; 176 } 177 return true; 178 } 179 if (line.indexOf("5D shell") >= 0) 180 moData.put("calculationType", calculationType = line); 181 return true; 182 } 183 makeNewAtomSet()184 private void makeNewAtomSet() { 185 // Spartan 16 files may have an empty first model 186 if (asc.ac == 0) 187 asc.removeCurrentAtomSet(); 188 asc.newAtomSet(); 189 } 190 191 @Override finalizeSubclassReader()192 protected void finalizeSubclassReader() throws Exception { 193 finalizeReaderASCR(); 194 // info out of order -- still a chance, at least for first model 195 if (asc.ac > 0 && spartanArchive != null && asc.bondCount == 0 196 && bondData != null) 197 spartanArchive.addBonds(bondData, 0); 198 if (moData != null) { 199 Float n = (Float) asc.atomSetInfo.get("HOMO_N"); 200 if (n != null) { 201 int i = n.intValue(); 202 moData.put("HOMO", Integer.valueOf(i)); 203 // TODO: This would take some work -- SOMO, degenerate HOMO etc. 204 //for (int j = orbitals.size(); --j >= 0;) 205 //orbitals.get(j).put("occupancy", Float.valueOf(j > i ? 0 : 2)); 206 207 } 208 } 209 } 210 readMyTransform()211 private void readMyTransform() throws Exception { 212 float[] mat; 213 String binaryCodes = rd(); 214 // last 16x4 bytes constitutes the 4x4 matrix, using doubles 215 String[] tokens = PT.getTokens(binaryCodes.trim()); 216 if (tokens.length < 16) 217 return; 218 byte[] bytes = new byte[tokens.length]; 219 for (int i = 0; i < tokens.length; i++) 220 bytes[i] = (byte) PT.parseIntRadix(tokens[i], 16); 221 mat = new float[16]; 222 for (int i = 16, j = bytes.length - 8; --i >= 0; j -= 8) 223 mat[i] = BC.bytesToDoubleToFloat(bytes, j, false); 224 setTransform(mat[0], mat[1], mat[2], mat[4], mat[5], mat[6], mat[8], 225 mat[9], mat[10]); 226 } 227 228 private final static String endCheck = "END Directory Entry "; 229 private String title; 230 231 SpartanArchive spartanArchive; 232 233 Map<String, String> titles; 234 readOutput()235 private void readOutput() throws Exception { 236 titles = new Hashtable<String, String>(); 237 SB header = new SB(); 238 int pt; 239 while (rd() != null && !line.startsWith("END ") && !line.startsWith("ENDOUTPUT")) { 240 header.append(line).append("\n"); 241 if ((pt = line.indexOf(")")) > 0) 242 titles.put("Title" + parseIntRange(line, 0, pt), (line 243 .substring(pt + 1).trim())); 244 } 245 asc.setInfo("fileHeader", header 246 .toString()); 247 } 248 readArchive()249 private String readArchive() throws Exception { 250 spartanArchive = new SpartanArchive(this, bondData, endCheck, 0); 251 String modelName = readArchiveHeader(); 252 if (modelName != null) 253 modelAtomCount = spartanArchive.readArchive(line, false, asc.ac, false); 254 return (constraints == null ? modelName : null); 255 } 256 257 private boolean haveCharges; 258 setCharges()259 private void setCharges() { 260 if (haveCharges || asc.ac == 0) 261 return; 262 haveCharges = (espCharges 263 && asc.setAtomSetCollectionPartialCharges("ESPCHARGES") 264 || natCharges && asc.setAtomSetCollectionPartialCharges("NATCHARGES") 265 || asc.setAtomSetCollectionPartialCharges("MULCHARGES") 266 || asc.setAtomSetCollectionPartialCharges("Q1_CHARGES") || asc 267 .setAtomSetCollectionPartialCharges("ESPCHARGES")); 268 } 269 readProperties()270 private void readProperties() throws Exception { 271 if (modelAtomCount == 0) { 272 rd(); 273 return; 274 } 275 if (spartanArchive == null) 276 spartanArchive = new SpartanArchive(this, bondData, endCheck, 277 modelAtomCount); 278 spartanArchive.readProperties(); 279 rd(); 280 setCharges(); 281 } 282 readArchiveHeader()283 private String readArchiveHeader() throws Exception { 284 String modelInfo = rd(); 285 if (debugging) 286 Logger.debug(modelInfo); 287 if (modelInfo.indexOf("Error:") == 0) // no archive here 288 return null; 289 asc.setCollectionName(modelInfo); 290 asc.setAtomSetName(modelInfo); 291 String modelName = rd(); 292 if (debugging) 293 Logger.debug(modelName); 294 // 5 17 11 18 0 1 17 0 RHF 3-21G(d) NOOPT FREQ 295 rd(); 296 return modelName; 297 } 298 setEnergy(float value)299 public void setEnergy(float value) { 300 asc.setAtomSetName(constraints + (constraints.length() == 0 ? "" : " ") + "Energy=" + value + " KJ"); 301 } 302 303 } 304