// $Id: // Exp $ // // FORESTER -- software libraries and applications // for evolutionary biology research and applications. // // Copyright (C) 2009-2010 Christian M. Zmasek // Copyright (C) 2009-2010 Burnham Institute for Medical Research // All rights reserved // // 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 Street, Fifth Floor, Boston, MA 02110-1301, USA // // Contact: phylosoft @ gmail . com // WWW: https://sites.google.com/site/cmzmasek/home/software/forester/ package org.forester.io.parsers.nexus; import java.io.BufferedReader; import java.io.IOException; import org.forester.evoinference.matrix.character.BasicCharacterStateMatrix; import org.forester.evoinference.matrix.character.CharacterStateMatrix; import org.forester.evoinference.matrix.character.CharacterStateMatrix.BinaryStates; import org.forester.io.parsers.util.ParserUtils; import org.forester.io.parsers.util.PhylogenyParserException; public class NexusBinaryStatesMatrixParser { private Object _nexus_source; private CharacterStateMatrix _matrix; private int _nchar; private int _ntax; public CharacterStateMatrix getMatrix() { return _matrix; } public int getNChar() { return _nchar; } private Object getNexusSource() { return _nexus_source; } public int getNTax() { return _ntax; } public void parse() throws IOException { reset(); final BufferedReader reader = ParserUtils.createReader( getNexusSource() ); String line; boolean in_matrix = false; int identifier_index = 0; int max_character_index = -1; while ( ( line = reader.readLine() ) != null ) { line = line.trim(); if ( ( line.length() > 0 ) && !line.startsWith( "#" ) && !line.startsWith( ">" ) ) { if ( line.toLowerCase().indexOf( NexusConstants.NCHAR.toLowerCase() ) >= 0 ) { final int i = line.toLowerCase().indexOf( NexusConstants.NCHAR.toLowerCase() ); String s = line.toLowerCase().substring( i + 6 ); s = s.replace( ';', ' ' ).trim(); setNChar( Integer.parseInt( s ) ); } else if ( line.toLowerCase().indexOf( NexusConstants.NTAX.toLowerCase() ) >= 0 ) { final int i = line.toLowerCase().indexOf( NexusConstants.NTAX.toLowerCase() ); String s = line.toLowerCase().substring( i + 5 ); s = s.replace( ';', ' ' ).trim(); setNTax( Integer.parseInt( s ) ); } else if ( line.toLowerCase().startsWith( NexusConstants.MATRIX.toLowerCase() ) ) { in_matrix = true; if ( getNTax() < 1 ) { throw new NexusFormatException( "did not encounter " + NexusConstants.NTAX ); } if ( getNChar() < 1 ) { throw new NexusFormatException( "did not encounter " + NexusConstants.NCHAR ); } if ( getMatrix() != null ) { throw new NexusFormatException( "more than one matrix present" ); } setMatrix( new BasicCharacterStateMatrix( getNTax(), getNChar() ) ); } else if ( line.toLowerCase().startsWith( NexusConstants.END.toLowerCase() ) ) { in_matrix = false; } else if ( in_matrix ) { final String[] line_ary = line.split( "\\s+" ); final String label = line_ary[ 0 ].trim(); String states_str = line_ary[ 1 ].trim(); if ( states_str.endsWith( ";" ) ) { in_matrix = false; states_str = states_str.substring( 0, states_str.length() - 1 ); } final char[] states = states_str.toCharArray(); getMatrix().setIdentifier( identifier_index, label ); int character_index = 0; for( final char state : states ) { if ( state == BinaryStates.PRESENT.toChar() ) { try { getMatrix().setState( identifier_index, character_index, BinaryStates.PRESENT ); } catch ( final ArrayIndexOutOfBoundsException ex ) { throw new NexusFormatException( "problem at line " + line + " [" + ex + "]" ); } } else if ( state == BinaryStates.ABSENT.toChar() ) { try { getMatrix().setState( identifier_index, character_index, BinaryStates.ABSENT ); } catch ( final ArrayIndexOutOfBoundsException ex ) { throw new NexusFormatException( "problem at line " + line + " [" + ex + "]" ); } } else { throw new NexusFormatException( "illegal state " + state ); } ++character_index; } if ( ( max_character_index > 0 ) && ( max_character_index != character_index ) ) { throw new NexusFormatException( "unequal number of characters at line " + line ); } max_character_index = character_index; ++identifier_index; } } } } private void reset() { setMatrix( null ); setNChar( -1 ); setNTax( -1 ); } private void setMatrix( final CharacterStateMatrix matrix ) { _matrix = matrix; } private void setNChar( final int nchar ) { _nchar = nchar; } private void setNTax( final int ntax ) { _ntax = ntax; } public void setSource( final Object nexus_source ) throws PhylogenyParserException, IOException { if ( nexus_source == null ) { throw new PhylogenyParserException( getClass() + ": attempt to parse null object." ); } _nexus_source = nexus_source; } }