/**
 * 
 * Written by Márton Münz and Philip C Biggin
 * Copyright (c) University of Oxford, United Kingdom
 * Visit http://sbcb.bioch.ox.ac.uk/jgromacs/
 * 
 * This source code file is part of JGromacs v1.0.
 * 
 * JGromacs v1.0 is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * JGromacs v1.0. 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 JGromacs v1.0. If not, see <http://www.gnu.org/licenses/>.
 * 
 */

package jgromacs.io;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import jgromacs.data.Alignment;
import jgromacs.data.Atom;
import jgromacs.data.IndexSet;
import jgromacs.data.IndexSetList;
import jgromacs.data.Point3D;
import jgromacs.data.PointList;
import jgromacs.data.Residue;
import jgromacs.data.Sequence;
import jgromacs.data.Structure;
import jgromacs.data.Trajectory;
import jgromacs.db.AtomType;
import jgromacs.db.ResidueType;


/**
 * This class contains static methods for IO of data objects
 *
 */
public class IOData {
	
	// IO Structures
	
	/**
	 * Reads structure from the given GRO file
	 * @param filename Input file name
	 * @return structure as a Structure object
	 * @throws IOException 
	 */
	public static Structure readStructureFromGRO(String filename) throws IOException{
		Structure ret = new Structure();
		ArrayList<String> lines = readFromFileToVector(filename);
		ret.setName(lines.get(0));
			lines.remove(0);
			lines.remove(0);
			String line; 
		 int currentResidue = -1;
		 Residue res = new Residue();
		for (int i= 0; i < lines.size()-1; i++) {
				line = (String)lines.get(i);
				Integer resindex = Integer.valueOf(line.substring(0,5).trim());
				String resname = line.substring(5,10).trim();
				String atomname = line.substring(10,15).trim();
				Integer atomindex = Integer.valueOf(line.substring(15,20).trim());
				Double x = Double.valueOf(line.substring(20,28).trim());
				Double y = Double.valueOf(line.substring(28,36).trim());
				Double z = Double.valueOf(line.substring(36,44).trim());
				if (resindex!=currentResidue) {
					if (i>0) ret.addResidue(res);	
					res = new Residue();
					res.setName(resname);
					res.setIndex(resindex);
					res.setResidueType(new ResidueType(resname));
					currentResidue = resindex;
				}
				Atom atom = new Atom();
				atom.setName(atomname);
				if (res.isAminoAcid()) atom.setAtomType(new AtomType(atomname.substring(0, 1)));
				else atom.setAtomType(new AtomType(atomname));
				atom.setIndex(atomindex);
				atom.setCoordinates(new Point3D(x, y, z));
				res.addAtom(atom);	
		}
		ret.addResidue(res);
		return ret;
	}	
	
	/**
	 * Reads structure from the given PDB file
	 * @param filename Input file name
	 * @return structure as a Structure object
	 * @throws IOException 
	 */
	public static Structure readStructureFromPDB(String filename) throws IOException{
		Structure ret = new Structure();
		ret.setName(filename);
		ArrayList<String> lines = readFromFileToVector(filename);
		 int currentResidue = -1;
		 Residue res = new Residue();
		boolean ok = true;
		boolean titleok = false;
	 for (int i= 0; i < lines.size(); i++) {
		String line = (String)lines.get(i);
		if (isTitleLine(line)&&!titleok) 
			{
			ret.setName(line.substring(10));
			titleok = true;
			}
		if (isModelEndLine(line)) ok = false;
		if (ok&&isAtomLine(line)) {
			Integer resindex = Integer.valueOf(line.substring(22,26).trim());
			String resname = line.substring(17,20).trim();
			String chainID = line.substring(21,22).trim();
			if (resindex!=currentResidue) {
				if (currentResidue!=-1) {
					ret.addResidue(res);
				}
				res = new Residue();
				res.setChainID(chainID);
				res.setName(resname);
				res.setIndex(resindex);
				res.setResidueType(new ResidueType(resname));
				currentResidue = resindex;
			}
			String atomname = line.substring(12,16).trim();
			String atomtype = "";
			if (line.length()>=78) atomtype = line.substring(76,78).trim();
			if (atomtype.equals("")){
				if (res.isAminoAcid()) atomtype = atomname.substring(0, 1);
				else atomtype = atomname;
			}
			Integer atomindex = Integer.valueOf(line.substring(6,11).trim());
			Double x = Double.valueOf(line.substring(30,38).trim())/10;
			Double y = Double.valueOf(line.substring(38,46).trim())/10;
			Double z = Double.valueOf(line.substring(46,54).trim())/10;
			double occupancy = Double.valueOf(line.substring(54,60).trim());
			double bvalue = Double.valueOf(line.substring(60,66).trim());
			Atom atom = new Atom();
			atom.setName(atomname);
			atom.setAtomType(new AtomType(atomtype));
			atom.setIndex(atomindex);
			atom.setCoordinates(new Point3D(x, y, z));
			atom.setOccupancy(occupancy);
			atom.setBvalue(bvalue);
			res.addAtom(atom);
		}		
	}
	ret.addResidue(res);
	return ret;
	}
	
	/**
	 * Reads the given model from the given PDB file
	 * @param filename Input file name
	 * @param model model to be read
	 * @return structure as a Structure object
	 * @throws IOException 
	 */
	public static Structure readStructureFromPDB(String filename, int model) throws IOException{
		if (model>howManyModelsInPDB(filename)) return null;
		Structure ret = new Structure();
		ret.setName(filename+"(Model_"+model+")");
		ArrayList<String> lines = readFromFileToVector(filename);
		 int currentResidue = -1;
		 Residue res = new Residue();
		boolean ok = true;
		int modelcounter = 1;
	 for (int i= 0; i < lines.size(); i++) {
		String line = (String)lines.get(i);
		
		if (isModelEndLine(line)) modelcounter++;
		if (modelcounter==model) ok = true;
		else ok = false;
		
		if (ok&isAtomLine(line)) {
			Integer resindex = Integer.valueOf(line.substring(22,26).trim());
			String resname = line.substring(17,20).trim();
			String chainID = line.substring(21,22).trim();
			if (resindex!=currentResidue) {
				if (currentResidue!=-1) {
					ret.addResidue(res);
				}
				res = new Residue();
				res.setChainID(chainID);
				res.setName(resname);
				res.setIndex(resindex);
				res.setResidueType(new ResidueType(resname));
				currentResidue = resindex;
			}
			String atomname = line.substring(12,16).trim();
			String atomtype = "";
			if (line.length()>=78) atomtype = line.substring(76,78).trim();
			if (atomtype.equals("")){
				if (res.isAminoAcid()) atomtype = atomname.substring(0, 1);
				else atomtype = atomname;
			}
			Integer atomindex = Integer.valueOf(line.substring(6,11).trim());
			Double x = Double.valueOf(line.substring(30,38).trim())/10;
			Double y = Double.valueOf(line.substring(38,46).trim())/10;
			Double z = Double.valueOf(line.substring(46,54).trim())/10;
			double occupancy = Double.valueOf(line.substring(54,60).trim());
			double bvalue = Double.valueOf(line.substring(60,66).trim());
			Atom atom = new Atom();
			atom.setName(atomname);
			atom.setAtomType(new AtomType(atomtype));
			atom.setIndex(atomindex);
			atom.setCoordinates(new Point3D(x, y, z));
			atom.setOccupancy(occupancy);
			atom.setBvalue(bvalue);
			res.addAtom(atom);
		}
		
	}
	ret.addResidue(res);
		return ret;
	}
	
	/**
	 * Returns the number of models in the given PDB file
	 * @param filename Input file name
	 * @return number of models
	 * @throws IOException 
	 */
	public static int howManyModelsInPDB( String filename) throws IOException{
		int ret = 0;
		boolean something = false;
		ArrayList<String> lines = readFromFileToVector(filename);
		 for (int i= 0; i < lines.size(); i++) {
			String line = (String)lines.get(i);
			if (isModelStartLine(line)) {
				ret++;
			}
			if (isAtomLine(line)) {
				something = true;
			}
		 }
	  if ((ret==0)&something) ret = 1;
	  return ret;
	}
	
	/**
	 * Reads an ensemble of structures from the given PDB file
	 * @param filename Input file name
	 * @return ensemble of structures as a Structure[] object
	 * @throws IOException 
	 */
	public static Structure[] readStructuresFromPDB(String filename) throws IOException{
		int howmany = howManyModelsInPDB(filename);
		if (howmany>1){
		Structure[] ret = new Structure[howmany];
		ArrayList<String> lines = readFromFileToVector(filename);		
		Structure s = new Structure();
		 int currentResidue = -1;
		 Residue res = new Residue();
		boolean started = false;
		int q = 0;
	 for (int i= 0; i < lines.size(); i++) {
		 String line = (String)lines.get(i);
		 if (isModelStartLine(line)){
			 	 s = new Structure();
				 currentResidue = -1;
				 res = new Residue();
				 q++;
				 if (!started) {
					q = 0;
				}
				 started = true;
		 }
		 if (isModelEndLine(line)){
			 s.addResidue(res);
			 s.setName(filename+"(Model_"+(q+1)+")");
			 ret[q] = s;	
		 }
	 	 
		 if (isAtomLine(line)) {
			Integer resindex = Integer.valueOf(line.substring(22,26).trim());
			String resname = line.substring(17,20).trim();
			String chainID = line.substring(21,22).trim();
			if (resindex!=currentResidue) {
				if (currentResidue!=-1) {
					s.addResidue(res);
				}
				res = new Residue();
				res.setChainID(chainID);
				res.setName(resname);
				res.setIndex(resindex);
				res.setResidueType(new ResidueType(resname));
				currentResidue = resindex;
			}
		
			String atomname = line.substring(12,16).trim();
			String atomtype = "";
			if (line.length()>=78) atomtype = line.substring(76,78).trim();
			if (atomtype.equals("")){
				if (res.isAminoAcid()) atomtype = atomname.substring(0, 1);
				else atomtype = atomname;
			}
			Integer atomindex = Integer.valueOf(line.substring(6,11).trim());
			Double x = Double.valueOf(line.substring(30,38).trim())/10;
			Double y = Double.valueOf(line.substring(38,46).trim())/10;
			Double z = Double.valueOf(line.substring(46,54).trim())/10;
			double occupancy = Double.valueOf(line.substring(54,60).trim());
			double bvalue = Double.valueOf(line.substring(60,66).trim());
			Atom atom = new Atom();
			atom.setName(atomname);
			atom.setAtomType(new AtomType(atomtype));
			atom.setIndex(atomindex);
			atom.setCoordinates(new Point3D(x, y, z));
			atom.setOccupancy(occupancy);
			atom.setBvalue(bvalue);
			res.addAtom(atom);
			
		 }		
	}
	
	return ret;
		}
		else {
			Structure[] ret = new Structure[1];
			ret[0] = readStructureFromPDB(filename);
			return ret;
		}
	}
	
	/**
	 * Reads an ensemble of structures from PDB files in the given directory
	 * @param path path of directory 
	 * @return ensemble of structures as a Structure[] object
	 * @throws IOException 
	 */
	public static Structure[] readStructuresFromPDBsInDirectory(String path) throws IOException{
		File dir = new File(path); 
		String[] children = dir.list(); 
		int numofPDBs = 0;
		for (int i = 0; i < children.length; i++) {
			String child = children[i];
			if (child.endsWith(".pdb")||child.endsWith(".PDB")) 
				numofPDBs++;
		}
		Structure[] ret = new Structure[numofPDBs];
		int counter = 0;
		for (int i = 0; i < children.length; i++) {
			String child = children[i];
			if (child.endsWith(".pdb")||child.endsWith(".PDB")){
				Structure s = IOData.readStructureFromPDB(path+"//"+child);
				ret[counter] = s;
				counter++;
			}
		}
		return ret;
	}
	
	/**
	 * Writes a structure to the given GRO file
	 * @param filename Output file name
	 * @param structure Structure object to be written out
	 * @throws IOException 
	 */
	public static void writeStructureToGRO(String filename, Structure structure) throws IOException{
		writeStringToFile(filename, structure.toStringAsGRO());
	}
	
	/**
	 * Writes a structure to the given PDB file
	 * @param filename Output file name
	 * @param structure Structure object to be written out
	 * @throws IOException 
	 */
	public static void writeStructureToPDB(String filename, Structure structure) throws IOException{
		writeStringToFile(filename, structure.toStringAsPDB());
	}

	// IO Trajectories
	
	/**
	 * Reads a trajectory from the given XTC or TRR file
	 * @param structure reference structure
	 * @param filename Input file name
	 * @return trajectory as a Trajectory object
	 * @throws IOException 
	 */
	public static Trajectory readTrajectory(Structure structure,  String filename) throws IOException{
	    Trajectory ret = new Trajectory(structure);
	    ret.setName(filename);
	    int counter=0;
        int counterFrame=0;
    	double firsttime = 0;
		double secondtime = 0;
	    ArrayList<String> rows = new ArrayList<String>();
		Runtime rt = Runtime.getRuntime();
        Process pr = rt.exec("gmxdump -f "+filename);
        BufferedReader input = new BufferedReader(new InputStreamReader(pr.getInputStream()));
        String line=null;
        while((line=input.readLine()) != null) {
               	if ((line.indexOf("time")>0)&(counterFrame==0)) firsttime = extractTime(line);
    	       	if ((line.indexOf("time")>0)&(counterFrame==1)) secondtime = extractTime(line);
    	       	if ((line.indexOf("frame")>0)&(counter>0)) {
    	       		PointList pointlist = extractPointList(rows);
    	      		ret.addFrame(pointlist);
    	       		counterFrame++;
    	       		rows = new ArrayList<String>();
    	       	}
    	       	rows.add(line);
    	       	counter++;
        }
        PointList pointlist = extractPointList(rows);
        ret.addFrame(pointlist);		
        input.close();
        ret.setStartTime(firsttime);
        ret.setTimeStep(secondtime-firsttime);
        ret.setName(filename.substring(0,filename.indexOf(".")));
        return ret;	                  
	}
	
	/**
	 * Reads a trajectory from the given dumped XTC or TRR file
	 * @param structure reference structure
	 * @param filename Input file name
	 * @return trajectory as a Trajectory object
	 * @throws IOException 
	 */
	public static Trajectory readDumpedTrajectory( Structure structure,  String filename) throws IOException{
		Trajectory ret = new Trajectory(structure);
		ret.setName(filename);
		File file = new File(filename);
		ArrayList<String> rows = new ArrayList<String>();
		double firsttime = 0;
		double secondtime = 0;
		BufferedReader input =  new BufferedReader(new FileReader(file));
		String line = null;		
		int counter=0;
		int counterFrame=0;
		while (( line = input.readLine()) != null) {
		      	if ((line.indexOf("time")>0)&(counterFrame==0)) firsttime = extractTime(line);
		      	if ((line.indexOf("time")>0)&(counterFrame==1)) secondtime = extractTime(line);
		      	if ((line.indexOf("frame")>0)&(counter>0)) {
		      		PointList pointlist = extractPointList(rows);
		       		ret.addFrame(pointlist);
		       		counterFrame++;
		       		rows = new ArrayList<String>();
		       	}
		    rows.add(line);
		    counter++;
		}
		PointList pointlist = extractPointList(rows);
	    ret.addFrame(pointlist);	
		ret.setStartTime(firsttime);
		ret.setTimeStep(secondtime-firsttime);
		ret.setName(filename);
		input.close();
		return ret;
	}
	
	private static double extractTime(String line){
		String str = line.substring(line.indexOf("time="));
		str = str.substring(0, str.indexOf(" "));
		str = str.substring(str.indexOf("=")+1);
		return Double.valueOf(str);
	}
	
	
	// IO Sequences and Alignments
	
	/**
	 * Reads a sequence from the given FASTA file
	 * @param filename Input file name
	 * @return sequence as a Sequence object
	 * @throws IOException 
	 */
	public static Sequence readSequenceFromFASTA(final String filename) throws IOException{
		Sequence ret = new Sequence();
		Boolean ok = false;
		ArrayList<String> rows = readFromFileToVector(filename);
		for (int i = 0; i < rows.size(); i++) {
			String row = (String)rows.get(i);
			if (row.indexOf(">")>=0) {
				row = row.substring(row.indexOf(">")+1);
				if (!ok) { ret.setName(row);
				ok = true;
				} else {
					return ret;
				}
			} else {
				ret.addPositionsFromString(row);
			}
		}
		return ret;
	}
	
	/**
	 * Reads an alignment from the given FASTA file
	 * @param filename Input file name
	 * @return alignment as an Alignment object
	 * @throws IOException 
	 */
	public static Alignment readAlignmentFromFASTA( String filename) throws IOException{
		ArrayList<String>rows = readFromFileToVector(filename);
		Alignment ret = new Alignment();
		Boolean ok = false;
		Sequence seq = new Sequence();
		for (int i = 0; i < rows.size(); i++) {
			String row = (String)rows.get(i);
			if (row.indexOf(">")>=0) {
				row = row.substring(row.indexOf(">")+1);
				if (ok) {
					Sequence sc = (Sequence)seq.clone();
					ret.addSequence(sc);
					seq = new Sequence(row);
				}
				else { 
				seq = new Sequence(row);
				ok = true;
				}
			} else {
				seq.addPositionsFromString(row);
			}
		}
		ret.addSequence(seq);
		return ret;
	}
	
	/**
	 * Writes a sequence to the given FASTA file
	 * @param filename Output file name
	 * @param sequence Sequence object to be written out
	 * @throws IOException 
	 * 
	 */
	public static void writeSequenceToFASTA(String filename, Sequence sequence) throws IOException{
		writeStringToFile(filename, sequence.toString());
	}

	/**
	 * Writes an alignment to the given FASTA file
	 * @param filename Output file name
	 * @param alignment Alignment object to be written out
	 * @throws IOException 
	 * 
	 */
	public static void writeAlignmentToFASTA( String filename, Alignment alignment) throws IOException{
		writeStringToFile(filename, alignment.toString());
	}
	
	// IO IndexSets and IndexSetLists
	
	/**
	 * Reads an index set from the given NDX file
	 * @param filename Input file name
	 * @return index set as an IndexSet object
	 * @throws IOException 
	 */
	public static IndexSet readIndexSetFromNDX( String filename) throws IOException{
		IndexSet ret;
		ArrayList<String> rows = readFromFileToVector(filename);
		for (int i = 0; i < rows.size(); i++) { 
			if (((String)rows.get(i)).equals("")) { 
				rows.remove(i); 
				i--; }
		}
		String row = (String)rows.get(0);
		row = row.substring(row.indexOf("[")+1, row.indexOf("]"));
		row = row.trim();
		ret = new IndexSet(row);
		for (int i = 1; i < rows.size(); i++) {
			row = (String)rows.get(i);
			if (row.indexOf("[")>=0) {
				return ret;
			}
			ArrayList<String> values = extractValues(row);
			for (int j = 0; j < values.size(); j++){
				String number = (String)values.get(j);
			if (!number.equals("")) {
				ret.addIndex(Integer.valueOf(number));
			}	
			}	
		}
		return ret;
	}
	
	/**
	 * Reads an index set list from the given NDX file
	 * @param filename Input file name
	 * @return index set list as an IndexSetList object
	 * @throws IOException 
	 */
	public static IndexSetList readIndexSetListFromNDX( String filename) throws IOException{
		IndexSetList ret = new IndexSetList();
		ArrayList<String> rows = readFromFileToVector(filename);
		String row = "";
		IndexSet set = new IndexSet();
		for (int i = 0; i < rows.size(); i++) {
			row = (String)rows.get(i);
			if (row.indexOf("[")>=0) {
				if (i>0) {
					ret.addIndexSet(set);
				}
				row = row.substring(row.indexOf("[")+1, row.indexOf("]"));
				row = row.trim();
				set = new IndexSet(row);	
			}
			else {
				ArrayList<String> values = extractValues(row);
				for (int j = 0; j < values.size(); j++){
					String number = (String)values.get(j);
				if (!number.equals("")) {
					set.addIndex(Integer.valueOf(number));
				} }				
			}
		}
		ret.addIndexSet(set);
		return ret;
	}
	
	/**
	 * Writes an index set to the given NDX file
	 * @param filename Output file name
	 * @param set IndexSet object to be written out
	 * @throws IOException 
	 * 
	 */
	public static void writeIndexSetToNDX(String filename, IndexSet set) throws IOException{
		writeStringToFile(filename, set.toString());
	}
	
	/**
	 * Writes an index set list to the given NDX file
	 * @param filename Output file name
	 * @param indexsetlist IndexSetList object to be written out
	 * @throws IOException 
	 * 
	 */
	public static void writeIndexSetListToNDX( String filename,  IndexSetList indexsetlist) throws IOException{
		writeStringToFile(filename, indexsetlist.toString());
	}
	
	// Running Gromacs commands from the Java code
	
	/**
	 * Executes Gromacs commands from within the Java code and reads 
	 * the listed output files back into JGromacs objects. (Note that
	 * the method can be used to execute not only Gromacs commands.) 
	 * The commands are run in the Unix shell (sh), so for example 
	 * shell pipes (>,>>,<,|) can also be used in the command line.
	 * The first element of the returned array is the standard output
	 * and next elements are the JGromacs objects read in.
	 * @param command Gromacs command to be executed
	 * @param filenames array of output file names to be read in
	 * @return array of JGromacs objects read from the files
	 * @throws IOException 
	 * 
	 */
	public static Object[] runGromacsCommand(String command, String[] filenames) throws IOException{
		Object[] ret = new Object[filenames.length+1];
		String[] cmd = {"sh", "-c", command};
		StringBuffer buf = new StringBuffer();
		String line;
		Process p = Runtime.getRuntime().exec(cmd);
		BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
		while ((line = input.readLine()) != null)  buf.append(line+"\n");
		input.close();
		ret[0] = buf.toString();
		for (int i = 0; i < filenames.length; i++) ret[i+1] = readFromFile(filenames[i]);
		return ret;
	}
		
	// Reading files automatically identifying their type
	
	/**
	 * Reads a JGromacs object (Structure, IndexSetList, Trajectory or Sequence) from a file
	 * automatically identifying the type of the file
	 * @param filename Input file name with correct extension
	 * @return JGromacs object
	 * @throws IOException 
	 * 
	 */
	public static Object readFromFile(String filename) throws IOException{
		if (isTrajectoryFile(filename)) return readTrajectory(new Structure(), filename);
		if (isGROFile(filename)) return readStructureFromGRO(filename);
		if (isPDBFile(filename)) return readStructureFromPDB(filename);
		if (isNDXFile(filename)) return readIndexSetListFromNDX(filename);
		if (isFASTAFile(filename)) return readSequenceFromFASTA(filename);
		return null;
	}
	
	
	// Private methods helping the public methods
	
	private static boolean isTrajectoryFile(String fn){
		return fn.toUpperCase().endsWith("XTC")|fn.toUpperCase().endsWith("TRR");
	}
	
	private static boolean isGROFile(String fn){
		return fn.toUpperCase().endsWith("GRO");
	}
	
	private static boolean isPDBFile(String fn){
		return fn.toUpperCase().endsWith("PDB");
	}
	
	private static boolean isNDXFile(String fn){
		return fn.toUpperCase().endsWith("NDX");
	}
	
	private static boolean isFASTAFile(String fn){
		return fn.toUpperCase().endsWith("FASTA");
	}
	
	
	private static boolean isModelStartLine( String row){
		return row.startsWith("MODEL");
	}
	
	private static boolean isModelEndLine( String row){
		return row.startsWith("ENDMDL");
	}
	
	private static boolean isAtomLine( String row){
		return row.startsWith("ATOM")|row.startsWith("HETATM");
	}
	
	private static boolean isTitleLine(String row){
		return row.startsWith("TITLE");
	}
	
	private static ArrayList<String> readFromFileToVector(String filename) throws IOException{
		ArrayList<String> ret = new ArrayList<String>();
		File file = new File(filename);
		BufferedReader input =  new BufferedReader(new FileReader(file));
		String line = null; 
		while (( line = input.readLine()) != null) ret.add(line);
		input.close();
		return ret;
	}
	
	private static ArrayList<String> extractValues(String s){
		s=s.replaceAll("       ", " ");
		s=s.replaceAll("      ", " ");
		s=s.replaceAll("     ", " ");
		s=s.replaceAll("    ", " ");
		s=s.replaceAll("   ", " ");
		s=s.replaceAll("  ", " ");
		s=s.trim();
	
		ArrayList<String> elements = new ArrayList<String>();
		while(s.indexOf(" ")>0){
		String element = s.substring(0,s.indexOf(" "));
		s = s.substring(s.indexOf(" ")+1,s.length());
		elements.add(element);
		}
		elements.add(s);
	
		return elements;
	}

	private static PointList extractPointList(ArrayList<String> rows){
		PointList ret = new PointList();
		String row = "";
		Point3D point;
		for (int i = 0; i < rows.size(); i++) {
			row = (String)rows.get(i);
			if (row.indexOf(" x[")>0) { point = extractPoint(row);
			ret.addPoint(point);
			}
		}
		return ret;
	}
	
	private static Point3D extractPoint(String s){
		String xstr = s.substring(s.indexOf("{")+1, s.indexOf(","));
		s = s.substring(s.indexOf(",")+1,s.length());
		String ystr = s.substring(0, s.indexOf(","));
		s = s.substring(s.indexOf(",")+1,s.length());
		String zstr = s.substring(0, s.indexOf("}"));
		return new Point3D(Double.valueOf(xstr),Double.valueOf(ystr),Double.valueOf(zstr));
	}
	
	private static void writeStringToFile(String filename, String str) throws IOException{
	File file = new File(filename);
	BufferedWriter output =  new BufferedWriter(new FileWriter(file));
	output.write(str);
	output.close();
	}
	
}
	
	