Hi,

Here is my little contribution to the JMol project: an ABINIT Reader.
ABINIT (www.abinit.org) is a Density Functional Theory Package to
compute total energy, electron density,... of a system of electrons and
nuclei.
An abinit input file contains information about the geometry of the
system and a lot of variables to define what to compute. Of course, only
the geometry information is usefull for jmol.
So far, ABINITReader only understand abinit *input* files. I intend to
make it also understand abinit *output* files in the future.

Actually, abinit essentially deals with crystals. Therefore, I would
like to implement an interface in JMol to enter the periodicity of the
crystal (basis vectors, space group, ...), the clipping box, etc.

Do you think it has something to do with the JMol project? 

I am waiting for your comments!


Regards

Fabian


-- 
**********
Fabian Dortu

Collegeberg 16
3000 Leuven
Belgium

Phone   : 32-475-599268
e-mails : [EMAIL PROTECTED]
          [EMAIL PROTECTED]
*********************************************** 
/*
 * Copyright 2001 The Jmol Development Team
 *
 *  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., 59 Temple Place, Suite 330, Boston, MA
 *  02111-1307  USA.
 */
package org.openscience.jmol;

import java.io.*;
import java.util.Vector;
import java.util.StringTokenizer;
import javax.vecmath.Point3f;
import java.lang.reflect.Array;

/**
 * Abinit summary (www.abinit.org)
 *   ABINIT is a package whose main program allows one to find the total 
 *   energy, charge density and electronic structure of systems made of 
 *   electrons and nuclei (molecules and periodic solids) within 
 *   Density Functional Theory (DFT), using pseudopotentials and a 
 *   planewave basis. ABINIT also includes options to optimize the 
 *   geometry according to the DFT forces and stresses, or to perform 
 *   molecular dynamics simulation using these forces, or to generate 
 *   dynamical matrices, Born effective charges, and dielectric tensors. 
 *
 *
 * An abinit input file is composed of many keywords arranged in a non-specific 
 * order. Each keyword is followed by one or more numbers (integers or 
 * floats depending of the keyword). Characters following a '#' are ignored.
 * The fisrt line of the file can be considered as a title. 
 * This implementaton supports only 1 dataset!!!
 *
 * <p> This reader was developed without the assistance or approval of
 * anyone from Network Computing Services, Inc. (the authors of XMol).
 * If you have problems, please contact the author of this code, not
 * the developers of XMol.
 *
 * @author Fabian Dortu ([EMAIL PROTECTED])
 * @version 1.0 */
public class ABINITReader implements ChemFileReader {
    
    /**
     * Create an ABINIT output reader.
     *
     * @param input source of ABINIT data
     */
    
    public static final double angstromPerBohr = 0.529177249;
    private StringTokenizer st;    // This variable will be used to parse the input file

    
    public ABINITReader(Reader input) {
	this.input = new BufferedReader(input);
    }
    
    /**
     * Whether bonds are enabled in the files and frames read.
     */
    private boolean bondsEnabled = true;
    
    /**
     * Sets whether bonds are enabled in the files and frames which are read.
     *
     * @param bondsEnabled if true, enables bonds.
     */
    public void setBondsEnabled(boolean bondsEnabled) {
	this.bondsEnabled = bondsEnabled;
    }
    
    /**
     * Read the ABINIT output.
     *
     * @return a ChemFile with the coordinates
     */
    public ChemFile read() throws IOException {
	
	ChemFile file = new ChemFile(bondsEnabled);
	
	int natom = 1; 
	int ntype = 1;
	double[] acell = new double[3];
	double[][] rprim = new double[3][3];
	String info = "";  
	String sn;

	String line;


	info = input.readLine();
	System.out.println(info);
	
	//Check if this is a multidataset file. Multidataset is not yet supported
	input.mark(1024*1024);   
	line = input.readLine();
	st = new StringTokenizer(line, " \t");
	sn = nextAbinitToken(input);

	while (sn != null) {
	    if (sn.equals("ndtset"))
		{
		    sn = nextAbinitToken(input);
		    if (FortranFormat.atof(sn) > 1)
			{
			    System.out.println("ABINITReader: multidataset not supported");
			    fireFrameRead();
			    return file;
			}
		}
	    sn = nextAbinitToken(input);
	}
	input.reset();

	//First pass through the file (get variables of known dimension)
	input.mark(1024*1024);   
	line = input.readLine();
	st = new StringTokenizer(line, " \t");
	sn = nextAbinitToken(input);

	while (sn != null) {
	    if (sn.equals("acell"))
		{
		    for (int i=0; i<3 ; i++)
			{

			    sn = nextAbinitToken(input);
			    int index=sn.indexOf("*");
			    if (index >= 0)    //Test if number format of type i*f
				{
				    int times = Integer.parseInt(sn.substring(0, index));
				    System.out.println("times : "+times);
				    double value = FortranFormat.atof(sn.substring(index+1));
				    System.out.println("value : "+value);
				    for (int j=i; j<i+times ; j++)
					{
					    acell[j] = value;
					}
				    i=i+times-1;
				}
			    else
				{
				    acell[i] = FortranFormat.atof(sn);
				}
			}

		    System.out.println("acell: "+acell[0]+" "+acell[1]+" "+acell[2]);
			    
		}
	    else if (sn.equals("rprim"))
		{
		    for (int i = 0; i < 3; i++) {
			for (int j = 0; j < 3; j++) {
			    sn = nextAbinitToken(input);	
			    rprim[i][j]=FortranFormat.atof(sn);
			}
		    }
		}
	    else if (sn.equals("ntype"))
		{
		    sn = nextAbinitToken(input);
		    ntype = Integer.parseInt(sn);
		}
	    else if (sn.equals("natom"))
		{
		    sn = nextAbinitToken(input);
		    natom = Integer.parseInt(sn);
		}
	    sn = nextAbinitToken(input);
	}



	//Initialize dynamic variables
	int[] zatnum=(int[]) Array.newInstance(int.class, ntype);
	int[] type=(int[]) Array.newInstance(int.class, natom);
	ChemFrame frame = new ChemFrame(natom);
	int[] dims = {natom,3};
	double[][] xangst = (double[][]) Array.newInstance(double.class, dims);		    
	double[][] xred = (double[][]) Array.newInstance(double.class, dims);

	//Second pass through the file 
	input.reset();
	sn = nextAbinitToken(input);

	while (sn != null) {
	    if (sn.equals("zatnum")) 
		{
		    for (int i = 0; i < ntype; i++) {
			sn = nextAbinitToken(input);
			zatnum[i]=Integer.parseInt(sn);
		    }
		}
	    else if (sn.equals("type"))    //type MUST BE after natom in the input file !!!BUG?!!!
		{
		    for (int i = 0; i < natom; i++) {
			sn = nextAbinitToken(input);
			int index=sn.indexOf("*");
			if (index >= 0)    //Test if number format of type i*i
			    {
				int times = Integer.parseInt(sn.substring(0, index));
				System.out.println("times : "+times);
				int value = Integer.parseInt(sn.substring(index+1));
				System.out.println("value : "+value);
				for (int j=i; j<i+times ; j++)
				    {
					type[j] = value;
				    }
				i=i+times-1;
			    }
			else
			    {
				type[i] = Integer.parseInt(sn);
			    }
		    }
		}
	    else if (sn.equals("xangst"))  
		{
		    for (int i = 0; i < natom; i++) {
			for (int j = 0; j < 3; j++) {
			    sn = nextAbinitToken(input);
			    xangst[i][j]=FortranFormat.atof(sn);
			}
		    }
		}
	    else if (sn.equals("xcart"))  
		{
		    for (int i = 0; i < natom; i++) {
			for (int j = 0; j < 3; j++) {
			    sn = nextAbinitToken(input);
			    xangst[i][j]=FortranFormat.atof(sn) * angstromPerBohr;
			}
		    }
		}
	    else if (sn.equals("xred"))
		{
		    for (int i = 0; i < natom; i++) {
			for (int j = 0; j < 3; j++) {
			    sn = nextAbinitToken(input);
			    xred[i][j]=FortranFormat.atof(sn);
			}
			xangst[i][0]=(xred[i][0]*rprim[0][0]+xred[i][1]*rprim[1][0]+xred[i][2]*rprim[2][0])*acell[0]*angstromPerBohr;
			xangst[i][1]=(xred[i][0]*rprim[0][1]+xred[i][1]*rprim[1][1]+xred[i][2]*rprim[2][1])*acell[1]*angstromPerBohr;
			xangst[i][2]=(xred[i][0]*rprim[0][2]+xred[i][1]*rprim[1][2]+xred[i][2]*rprim[2][2])*acell[2]*angstromPerBohr;
		    }
		}
	    sn = nextAbinitToken(input);
	}	
	

	
	frame.setInfo(info);
	for (int i = 0; i < natom ; i++) {
	    int atomIndex = frame.addAtom(zatnum[type[i]-1] , (float) xangst[i][0], (float) xangst[i][1], (float) xangst[i][2]);
	    
	}
    	
	file.addFrame(frame);
	fireFrameRead();
	return file;
    }
    
    /**
     * Find the next token of an abinit file
     */
    public String nextAbinitToken(BufferedReader input) throws IOException {
	String line;
	String sn;
	while (!st.hasMoreTokens() && input.ready())
	    {
		line = input.readLine();
		st = new StringTokenizer(line, " \t");
	    }
	if (st.hasMoreTokens())
	    {
		sn = st.nextToken();
		if (sn.startsWith("#"))
		    {
			line = input.readLine();
			if (input.ready())
			    {
				st = new StringTokenizer(line, " \t");
				sn = nextAbinitToken(input);
			    }
		    }
	    }
	else
	    sn = null;
	
	return sn;
    }

    /**
     * Holder of reader event listeners.
     */
    private Vector listenerList = new Vector();
    
    /**
     * An event to be sent to listeners. Lazily initialized.
     */
    private ReaderEvent readerEvent = null;
    
    /**
     * Adds a reader listener.
     *
     * @param l the reader listener to add.
     */
    public void addReaderListener(ReaderListener l) {
	listenerList.addElement(l);
    }
    
    /**
     * Removes a reader listener.
     *
     * @param l the reader listener to remove.
     */
    public void removeReaderListener(ReaderListener l) {
	listenerList.removeElement(l);
    }
    
    /**
     * Sends a frame read event to the reader listeners.
     */
    private void fireFrameRead() {
	for (int i = 0; i < listenerList.size(); ++i) {
	    ReaderListener listener = (ReaderListener) listenerList.elementAt(i);
	    // Lazily create the event:
	    if (readerEvent == null) {
		readerEvent = new ReaderEvent(this);
	    }
	    listener.frameRead(readerEvent);
	}
    }
    
    private BufferedReader input;
}

/*
 * Copyright 2001 The Jmol Development Team
 *
 *  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., 59 Temple Place, Suite 330, Boston, MA
 *  02111-1307  USA.
 */
package org.openscience.jmol;

import java.io.Reader;
import java.io.BufferedReader;
import java.io.IOException;

/**
 * A factory for creating ChemFileReaders.
 * The type of reader created is determined from the input.
 *
 * @author  Bradley A. Smith ([EMAIL PROTECTED])
 */
public abstract class ReaderFactory {

  /**
   * Creates a ChemFileReader of the type determined by
   * reading the input. The input is read line-by-line
   * until a line containing an identifying string is
   * found.
   *
   * @return  If the input type is determined, a
   *   ChemFileReader subclass is returned; otherwise,
   *   null is returned.
   * @exception IOException  if an I/O error occurs
   */
  public static ChemFileReader createReader(Reader input) throws IOException {

    BufferedReader buffer = new BufferedReader(input);
    String line = null;

    if (buffer.markSupported()) {

      // The mark and reset on the buffer, is so that we can read
      // without screwing up the other tests below
      buffer.mark(255);
      line = getLine(buffer);
      buffer.reset();
      
      // If XML, assume CML.
      if (line != null && line.startsWith("<?xml")) {
        return new CMLReader(buffer);
      }


      // ADDED BY Fabian Dortu
      // Abinit 
      // We test the presence of an essential keywords, 
      // for instance 'natom'.
      buffer.mark(1024*1024);
      while ((buffer.ready()) && (line != null)) {
	  line = buffer.readLine();
	  if (line.indexOf("natom") >= 0)
	      {
		  buffer.reset();
		  return new ABINITReader(buffer);
	      }
      }
      buffer.reset();
      //END ADDED BY Fabian Dortu
      
      buffer.mark(1024);
      line = buffer.readLine();
      
      // If the first line contains mm1gp, then the file is identified
      // as a Ghemical Molecular Dynamics file
      if (line != null && line.indexOf("mm1gp") >= 0) {
        return new GhemicalMMReader(buffer);
      }

     

      buffer.readLine();
      buffer.readLine();
      String line4 = buffer.readLine();
      buffer.reset();

      // If the fourth line contains the MDL Ctab version tag,
      // the file is identified as an MDL file.
      if (line4 != null && line4.trim().endsWith("V2000")) {
        return new MdlReader(buffer);
      }

      // An integer on the first line is a special test for XYZ files
      try {
        if (line != null) {
          new Integer(line.trim());
          return new XYZReader(buffer);
        }
      } catch (NumberFormatException nfe) {
        // Integer not found on first line; therefore not a XYZ file
      }

    } else {
      line = buffer.readLine();
    }

    /* Search file for a line containing an identifying keyword */
    while (buffer.ready() && (line != null)) {
      if (line.indexOf("Gaussian 98:") >= 0) {
        return new Gaussian98Reader(buffer);
      } else if (line.indexOf("Gaussian 95:") >= 0) {
        return new Gaussian94Reader(buffer);
      } else if (line.indexOf("Gaussian 94:") >= 0) {
        return new Gaussian94Reader(buffer);
      } else if (line.indexOf("Gaussian 92:") >= 0) {
        return new Gaussian92Reader(buffer);
      } else if (line.indexOf("Gaussian G90") >= 0) {
        return new Gaussian90Reader(buffer);
      } else if (line.indexOf("GAMESS") >= 0) {
        return new GamessReader(buffer);
      } else if (line.indexOf("ACES2") >= 0) {
        return new Aces2Reader(buffer);
      } else if (line.indexOf("Amsterdam Density Functional") >= 0) {
        return new ADFReader(buffer);
      } else if (line.indexOf("DALTON") >= 0) {
        return new DaltonReader(buffer);
      } else if (line.indexOf("Jaguar") >= 0) {
        return new JaguarReader(buffer);
      } else if (line.indexOf("MOPAC") >= 0) {
        return new MopacReader(buffer);
      } else if (line.startsWith("HEADER")) {
        return new PDBReader(buffer);
      } else if (line.startsWith("molstruct")) {
        return new CACheReader(buffer);
      }
      line = buffer.readLine();
    }
    return null;
  }

  /**
   * Reads a line with special XML character handling. Any whitespace characters at
   * the beginning of the line are ignored. The end-tag character '>' is
   * considered an end-of-line character.
   *
   * @param buffer the input from which to read.
   * @return the line read.
   */
  static String getLine(BufferedReader buffer) throws IOException {

    StringBuffer sb1 = new StringBuffer();
    int c1 = buffer.read();
    while ((c1 > 0)
            && ((c1 == '\n') || (c1 == '\r') || (c1 == ' ')
              || (c1 == '\t'))) {
      c1 = buffer.read();
    }
    while ((c1 > 0) && (c1 != '\n') && (c1 != '\r') && (c1 != '>')) {
      sb1.append((char) c1);
      c1 = buffer.read();
    }
    if (c1 == '>') {
      sb1.append((char) c1);
    }
    return sb1.toString();
  }
}

Reply via email to