All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jmol.adapter.readers.molxyz.MolReader Maven / Gradle / Ivy

There is a newer version: 14.31.10
Show newest version
/* $RCSfile$
 * $Author: hansonr $
 * $Date: 2006-10-22 14:12:46 -0500 (Sun, 22 Oct 2006) $
 * $Revision: 5999 $
 *
 * Copyright (C) 2003-2005  Miguel, Jmol Development, www.jmol.org
 *
 * Contact: [email protected]
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *
 *  This library 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
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 */

package org.jmol.adapter.readers.molxyz;

import javajs.util.PT;

import org.jmol.adapter.smarter.AtomSetCollectionReader;
import org.jmol.adapter.smarter.Atom;
import org.jmol.api.JmolAdapter;
import org.jmol.util.Logger;

/**
 * A reader for MDLI mol and sdf files.
 * 

* * http://www.mdli.com/downloads/public/ctfile/ctfile.jsp *

* * also: http://www.mdl.com/downloads/public/ctfile/ctfile.pdf * * simple symmetry extension via load command: 9/2006 [email protected] * * setAtomCoord(atom, x, y, z) applySymmetryAndSetTrajectory() * * simple 2D-->3D conversion using * * load "xxx.mol" FILTER "2D" * */ public class MolReader extends AtomSetCollectionReader { /* * from ctfile.pdf: * * $MDL REV 1 date/time * $MOL * $HDR * [Molfile Header Block (see Chapter 4) = name, pgm info, comment] * $END HDR * $CTAB * [Ctab Block (see Chapter 2) = count + atoms + bonds + lists + props] * $END CTAB * $RGP * rrr [where rrr = Rgroup number] * $CTAB * [Ctab Block] * $END CTAB * $END RGP * $END MOL */ private boolean optimize2D; private boolean haveAtomSerials; protected String dimension; protected boolean allow2D = true; private int iatom0; private V3000Rdr vr; @Override public void initializeReader() throws Exception { optimize2D = checkFilterKey("2D"); } @Override protected boolean checkLine() throws Exception { boolean isMDL = (line.startsWith("$MDL")); if (isMDL) { discardLinesUntilStartsWith("$HDR"); rd(); if (line == null) { Logger.warn("$HDR not found in MDL RG file"); continuing = false; return false; } } else if (line.equals("M END")) return true; if (doGetModel(++modelNumber, null)) { iatom0 = asc.ac; processMolSdHeader(); processCtab(isMDL); vr = null; if (isLastModel(modelNumber)) { continuing = false; return false; } } if (line != null && line.indexOf("$$$$") < 0) discardLinesUntilStartsWith("$$$$"); return true; } @Override public void finalizeSubclassReader() throws Exception { finalizeReaderMR(); } protected void finalizeReaderMR() throws Exception { if (optimize2D) set2D(); isTrajectory = false; finalizeReaderASCR(); } private void processMolSdHeader() throws Exception { /* * obviously we aren't being this strict, but for the record: * * from ctfile.pdf (October 2003): * * Line 1: Molecule name. This line is unformatted, but like all * other lines in a molfile may not extend beyond column 80. * If no name is available, a blank line must be present. * Caution: This line must not contain any of the reserved * tags that identify any of the other CTAB file types * such as $MDL (RGfile), $$$$ (SDfile record separator), * $RXN (rxnfile), or $RDFILE (RDfile headers). * * Line 2: This line has the format: * IIPPPPPPPPMMDDYYHHmmddSSssssssssssEEEEEEEEEEEERRRRRR * (FORTRAN: A2<--A8--><---A10-->A2I2<--F10.5-><---F12.5--><-I6-> ) * User's first and last initials (l), program name (P), * date/time (M/D/Y,H:m), dimensional codes (d), scaling factors (S, s), * energy (E) if modeling program input, internal * registry number (R) if input through MDL form. A blank line can be * substituted for line 2. If the internal registry number is more than * 6 digits long, it is stored in an M REG line (described in Chapter 3). * * Line 3: A line for comments. If no comment is entered, a blank line * must be present. */ String header = ""; String thisDataSetName = line.trim(); header += line + "\n"; asc.setCollectionName(thisDataSetName); rd(); if (line == null) return; header += line + "\n"; dimension = (line.length() < 22 ? "3D" : line.substring(20, 22)); if (dimension.equals("2D")) { if (!allow2D) throw new Exception("File is 2D, not 3D"); appendLoadNote("This model is 2D. Its 3D structure has not been generated."); } asc.setInfo("dimension", dimension); //line 3: comment rd(); if (line == null) return; line = line.trim(); header += line + "\n"; if (line.length() != 0) { thisDataSetName += ": " + line; } Logger.info(header); checkCurrentLineForScript(); asc.setInfo("fileHeader", header); newAtomSet(thisDataSetName); } private void processCtab(boolean isMDL) throws Exception { if (isMDL) discardLinesUntilStartsWith("$CTAB"); if (rd() == null) return; if (line.indexOf("V3000") >= 0) { optimize2D = (dimension.equals("2D")); vr = ((V3000Rdr) getInterface("org.jmol.adapter.readers.molxyz.V3000Rdr")).set(this); discardLinesUntilContains("COUNTS"); vr.readAtomsAndBonds(getTokens()); } else { readAtomsAndBonds(parseIntRange(line, 0, 3), parseIntRange(line, 3, 6)); } applySymmetryAndSetTrajectory(); } // 0 1 2 3 4 5 6 7 // 01234567890123456789012345678901234567890123456789012345678901234567890 // xxxxx.xxxxyyyyy.yyyyzzzzz.zzzz aaaddcccssshhhbbbvvvHHHrrriiimmmnnneee private void readAtomsAndBonds(int ac, int bc) throws Exception { for (int i = 0; i < ac; ++i) { rd(); int len = line.length(); String elementSymbol; float x, y, z; int charge = 0; int isotope = 0; int iAtom = Integer.MIN_VALUE; x = parseFloatRange(line, 0, 10); y = parseFloatRange(line, 10, 20); z = parseFloatRange(line, 20, 30); if (len < 34) { // deal with older Mol format where nothing after the symbol is used elementSymbol = line.substring(31).trim(); } else { elementSymbol = line.substring(31, 34).trim(); if (len >= 39) { int code = parseIntRange(line, 36, 39); if (code >= 1 && code <= 7) charge = 4 - code; code = parseIntRange(line, 34, 36); if (code != 0 && code >= -3 && code <= 4) { isotope = JmolAdapter.getNaturalIsotope(JmolAdapter .getElementNumber(elementSymbol)); switch (isotope) { case 0: break; case 1: isotope = -code; break; default: isotope += code; } } //if (len >= 63) { this field is not really an atom number. It's for atom-atom mapping in reaction files // iAtom = parseIntRange(line, 60, 63); // if (iAtom == 0) // iAtom = Integer.MIN_VALUE; //} // previous model in series may have atom numbers indicated if (iAtom == Integer.MIN_VALUE && haveAtomSerials) iAtom = i + 1; } } addMolAtom(iAtom, isotope, elementSymbol, charge, x, y, z); } // read bonds for (int i = 0; i < bc; ++i) { rd(); String iAtom1, iAtom2; int stereo = 0; iAtom1 = line.substring(0, 3).trim(); iAtom2 = line.substring(3, 6).trim(); int order = parseIntRange(line, 6, 9); if (optimize2D && order == 1 && line.length() >= 12) stereo = parseIntRange(line, 9, 12); order = fixOrder(order, stereo); if (haveAtomSerials) asc.addNewBondFromNames(iAtom1, iAtom2, order); else asc.addNewBondWithOrder(iatom0 + parseIntStr(iAtom1) - 1, iatom0 + parseIntStr(iAtom2) - 1, order); } // read V2000 user data while (rd() != null && line.indexOf("$$$$") != 0) { if (line.toUpperCase().contains("_PARTIAL_CHARGES")) { try { Atom[] atoms = asc.atoms; for (int i = parseIntStr(rd()); --i >= 0;) { String[] tokens = PT.getTokens(rd()); int atomIndex = parseIntStr(tokens[0]) + iatom0 - 1; float partialCharge = parseFloatStr(tokens[1]); if (!Float.isNaN(partialCharge)) atoms[atomIndex].partialCharge = partialCharge; } } catch (Exception e) { return; } } } } public void addMolAtom(int iAtom, int isotope, String elementSymbol, int charge, float x, float y, float z) { switch (isotope) { case 0: break; case -1: elementSymbol = "D"; break; case -2: elementSymbol = "T"; break; default: elementSymbol = isotope + elementSymbol; } if (optimize2D && z != 0) optimize2D = false; Atom atom = new Atom(); atom.elementSymbol = elementSymbol; atom.formalCharge = charge; setAtomCoordXYZ(atom, x, y, z); if (iAtom == Integer.MIN_VALUE) { asc.addAtom(atom); } else { haveAtomSerials = true; atom.atomSerial = iAtom; asc.addAtomWithMappedSerialNumber(atom); } } public int fixOrder(int order, int stereo) { switch (order) { default: case 0: case -10: return 1; // smiles parser error case 1: switch (stereo) { case 1: // UP return JmolAdapter.ORDER_STEREO_NEAR; case 3: // DOWN, V3000 case 6: // DOWN return JmolAdapter.ORDER_STEREO_FAR; } break; case 2: case 3: break; case 4: return JmolAdapter.ORDER_AROMATIC; case 5: return JmolAdapter.ORDER_PARTIAL12; case 6: return JmolAdapter.ORDER_AROMATIC_SINGLE; case 7: return JmolAdapter.ORDER_AROMATIC_DOUBLE; case 8: case 9: // haptic return JmolAdapter.ORDER_PARTIAL01; } return order; } public void addMolBond(String iAtom1, String iAtom2, int order, int stereo) { order = fixOrder(order, stereo); if (haveAtomSerials) asc.addNewBondFromNames(iAtom1, iAtom2, order); else asc.addNewBondWithOrder(iatom0 + parseIntStr(iAtom1) - 1, iatom0 + parseIntStr(iAtom2) - 1, order); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy