--- /dev/null
+// $Id:
+// forester -- software libraries and applications
+// for genomics and evolutionary biology research.
+//
+// Copyright (C) 2010 Christian M Zmasek
+// Copyright (C) 2010 Sanford-Burnham Medical Research Institute
+// 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: www.phylosoft.org/forester
+
+package org.forester.development;
+
+import java.awt.Color;
+import java.awt.Graphics;
+
+import javax.swing.JComponent;
+
+public abstract class AbstractRenderer extends JComponent {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 7236434322552764776L;
+ static final Color DEFAULT_COLOR = new Color( 0, 0, 0 );
+ static final Color MARKED_COLOR = new Color( 255, 255, 0 );
+ static final Color USER_FLAGGED_COLOR = new Color( 255, 0, 255 );
+ static final Color SELECTED_COLOR = new Color( 255, 0, 0 );
+ int _x;
+ int _y;
+ int _well_size;
+ byte _status;
+
+ public AbstractRenderer() {
+ }
+
+ abstract MsaRenderer getParentPlateRenderer();
+
+ byte getStatus() {
+ return _status;
+ }
+
+ int getWellSize() {
+ return _well_size;
+ }
+
+ @Override
+ public int getX() {
+ return _x;
+ }
+
+ @Override
+ public int getY() {
+ return _y;
+ }
+
+ abstract boolean isSelected();
+
+ @Override
+ public abstract void paint( Graphics g );
+
+ abstract void setIsSelected( boolean flag );
+
+ void setStatus( final byte status ) {
+ _status = status;
+ }
+
+ void setWellSize( final int well_size ) {
+ _well_size = well_size;
+ }
+
+ void setX( final int x ) {
+ _x = x;
+ }
+
+ void setY( final int y ) {
+ _y = y;
+ }
+}
--- /dev/null
+// $Id:
+// FORESTER -- software libraries and applications
+// for evolutionary biology research and applications.
+//
+// Copyright (C) 2008-2009 Christian M. Zmasek
+// Copyright (C) 2008-2009 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: www.phylosoft.org/forester
+
+package org.forester.development;
+
+import java.util.Random;
+
+import org.forester.phylogeny.Phylogeny;
+import org.forester.phylogeny.PhylogenyMethods;
+import org.forester.phylogeny.PhylogenyNode;
+
+public final class DevelopmentTools {
+
+ /**
+ * Creates a completely unbalanced Phylogeny with i external nodes.
+ *
+ * @return a newly created unbalanced Phylogeny
+ */
+ // public static Phylogeny createUnbalancedTree( int i ) {
+ //
+ // Phylogeny t1 = null;
+ //
+ // try {
+ // PhylogenyFactory factory = ParserBasedPhylogenyFactory.getInstance();
+ // t1 = factory.create( ":S=", new SimpleNHXParser() );
+ //
+ // t1.setRooted( true );
+ //
+ // for ( int j = 1; j < i; ++j ) {
+ // t1.addNodeAndConnect( "", "" );
+ // }
+ // t1.setRoot( t1.getFirstExternalNode().getRoot() );
+ // t1.calculateRealHeight();
+ // }
+ //
+ // catch ( PhylogenyParserException e ) {
+ // System.err
+ // .println( "Unexpected exception during \"createUnbalancedTree\":" );
+ // System.err.println( e.toString() );
+ // System.exit( -1 );
+ // }
+ //
+ // return t1;
+ // }
+ private DevelopmentTools() {
+ }
+
+ /**
+ * Creates a completely balanced rooted phylogeny with a given number of levels and
+ * children per node.
+ *
+ * @param levels
+ * @param children_per_node
+ * @return a completely balanced rooted phylogeny
+ */
+ public static Phylogeny createBalancedPhylogeny( final int levels, final int children_per_node ) {
+ final PhylogenyNode root = new PhylogenyNode();
+ final Phylogeny p = new Phylogeny();
+ p.setRoot( root );
+ p.setRooted( true );
+ DevelopmentTools.createBalancedPhylogenyRecursion( levels, children_per_node, root );
+ return p;
+ }
+
+ private static void createBalancedPhylogenyRecursion( int current_level,
+ final int children_per_node,
+ final PhylogenyNode current_node ) {
+ if ( current_level > 0 ) {
+ --current_level;
+ for( int i = 0; i < children_per_node; ++i ) {
+ final PhylogenyNode new_node = new PhylogenyNode();
+ current_node.addAsChild( new_node );
+ DevelopmentTools.createBalancedPhylogenyRecursion( current_level, children_per_node, new_node );
+ }
+ }
+ }
+
+ /**
+ * Sets the species name of the external Nodes of Phylogeny t to 1, 1+i, 2,
+ * 2+i, 3, 3+i, .... Examples: i=2: 1, 3, 2, 4 i=4: 1, 5, 2, 6, 3, 7, 4, 8
+ * i=8: 1, 9, 2, 10, 3, 11, 4, 12, ...
+ */
+ public static void intervalNumberSpecies( final Phylogeny t, final int i ) {
+ if ( ( t == null ) || t.isEmpty() ) {
+ return;
+ }
+ PhylogenyNode n = t.getFirstExternalNode();
+ int j = 1;
+ boolean odd = true;
+ while ( n != null ) {
+ if ( odd ) {
+ PhylogenyMethods.setScientificName( n, j + "" );
+ }
+ else {
+ PhylogenyMethods.setScientificName( n, ( j + i ) + "" );
+ j++;
+ }
+ odd = !odd;
+ n = n.getNextExternalNode();
+ }
+ }
+
+ /**
+ * Sets the species namea of the external Nodes of Phylogeny t to descending
+ * integers, ending with 1.
+ */
+ public static void numberSpeciesInDescOrder( final Phylogeny t ) {
+ if ( ( t == null ) || t.isEmpty() ) {
+ return;
+ }
+ PhylogenyNode n = t.getFirstExternalNode();
+ int j = t.getRoot().getNumberOfExternalNodes();
+ while ( n != null ) {
+ PhylogenyMethods.setTaxonomyCode( n, j + "" );
+ j--;
+ n = n.getNextExternalNode();
+ }
+ }
+
+ /**
+ * Sets the species namea of the external Nodes of Phylogeny t to ascending
+ * integers, starting with 1.
+ */
+ public static void numberSpeciesInOrder( final Phylogeny t ) {
+ if ( ( t == null ) || t.isEmpty() ) {
+ return;
+ }
+ PhylogenyNode n = t.getFirstExternalNode();
+ int j = 1;
+ while ( n != null ) {
+ PhylogenyMethods.setScientificName( n, j + "" );
+ j++;
+ n = n.getNextExternalNode();
+ }
+ }
+
+ /**
+ * Sets the species names of the external Nodes of Phylogeny t to a random
+ * positive integer number between (and including) min and max.
+ *
+ * @param t
+ * whose external species names are to be randomized
+ * @param min
+ * minimal value for random numbers
+ * @param max
+ * maximum value for random numbers
+ */
+ public static void randomizeSpecies( final int min, final int max, final Phylogeny t ) {
+ if ( ( t == null ) || t.isEmpty() ) {
+ return;
+ }
+ final int mi = Math.abs( min );
+ final int ma = Math.abs( max );
+ final Random r = new Random();
+ PhylogenyNode n = t.getFirstExternalNode();
+ while ( n != null ) {
+ final String code = ( ( Math.abs( r.nextInt() ) % ( ma - mi + 1 ) ) + mi ) + "";
+ PhylogenyMethods.setTaxonomyCode( n, code );
+ n = n.getNextExternalNode();
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+// $Id:
+// forester -- software libraries and applications
+// for genomics and evolutionary biology research.
+//
+// Copyright (C) 2010 Christian M Zmasek
+// Copyright (C) 2010 Sanford-Burnham Medical Research Institute
+// 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: www.phylosoft.org/forester
+
+package org.forester.development;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintStream;
+import java.net.URL;
+import java.net.URLConnection;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXException;
+
+public class HmmerRest {
+
+ final static String LIST_SEPARATOR = "%0A";
+ final static String LINE_SEPARATOR = "\n";
+ private final static String BASE_URL = "http://pfam.sanger.ac.uk/search/sequence";
+
+ public static void main( final String[] args ) {
+ final String seq = "MASTENNEKDNFMRDTASRSKKSRRRSLWIAAGAVPTAIALSLSLASPA"
+ + "AVAQSSFGSSDIIDSGVLDSITRGLTDYLTPRDEALPAGEVTYPAIEGLP"
+ + "AGVRVNSAEYVTSHHVVLSIQSAAMPERPIKVQLLLPRDWYSSPDRDFPE"
+ + "IWALDGLRAIEKQSGWTIETNIEQFFADKNAIVVLPVGGESSFYTDWNEP"
+ + "NNGKNYQWETFLTEELAPILDKGFRSNGERAITGISMGGTAAVNIATHNP"
+ + "EMFNFVGSFSGYLDTTSNGMPAAIGAALADAGGYNVNAMWGPAGSERWLE"
+ + "NDPKRNVDQLRGKQVYVSAGSGADDYGQDGSVATGPANAAGVGLELISRM"
+ + "TSQTFVDAANGAGVNVIANFRPSGVHAWPYWQFEMTQAWPYMADSLGMSR"
+ + "EDRGADCVALGAIADATADGSLGSCLNNEYLVANGVGRAQDFTNGRAYWS"
+ + "PNTGAFGLFGRINARYSELGGPDSWLGFPKTRELSTPDGRGRYVHFENGS"
+ + "IYWSAATGPWEIPGDMFTAWGTQGYEAGGLGYPVGPAKDFNGGLAQEFQG"
+ + "GYVLRTPQNRAYWVRGAISAKYMEPGVATTLGFPTGNERLIPGGAFQEFT"
+ + "NGNIYWSASTGAHYILRGGIFDAWGAKGYEQGEYGWPTTDQTSIAAGGET" + "ITFQNGTIRQVNGRIEESR";
+ final String query = "seq=" + seq + "" + "&" + "output=xml";
+ String result = "";
+ try {
+ result = getResult( query );
+ }
+ catch ( final IOException e ) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ System.out.println( result );
+ final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ Document dom = null;
+ try {
+ //Using factory get an instance of document builder
+ final DocumentBuilder db = dbf.newDocumentBuilder();
+ //parse using builder to get DOM representation of the XML file
+ dom = db.parse( new ByteArrayInputStream( result.getBytes() ) );
+ }
+ catch ( final ParserConfigurationException pce ) {
+ pce.printStackTrace();
+ }
+ catch ( final SAXException se ) {
+ se.printStackTrace();
+ }
+ catch ( final IOException ioe ) {
+ ioe.printStackTrace();
+ }
+ final Element docEle = dom.getDocumentElement();
+ final NodeList nl = docEle.getElementsByTagName( "job" );
+ String result_url = "";
+ for( int i = 0; i < nl.getLength(); i++ ) {
+ //System.out.println( nl.item( i ) );
+ result_url = getTextValue( ( Element ) nl.item( i ), "result_url" );
+ }
+ System.out.println( "result url = " + result_url );
+ //gettin the result....
+ try {
+ //do what you want to do before sleeping
+ Thread.sleep( 5000 );//sleep for x ms
+ //do what you want to do after sleeptig
+ }
+ catch ( final InterruptedException ie ) {
+ ie.printStackTrace();
+ }
+ try {
+ result = getResult( result_url, "" );
+ }
+ catch ( final IOException e ) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ System.out.println( result );
+ }
+
+ private static String getTextValue( final Element ele, final String tagName ) {
+ String textVal = null;
+ final NodeList nl = ele.getElementsByTagName( tagName );
+ if ( ( nl != null ) && ( nl.getLength() > 0 ) ) {
+ final Element el = ( Element ) nl.item( 0 );
+ textVal = el.getFirstChild().getNodeValue();
+ }
+ return textVal;
+ }
+
+ public static String getResult( final String base_url, final String query ) throws IOException {
+ System.out.println( query );
+ final URL url = new URL( base_url );
+ final URLConnection urlc = url.openConnection();
+ urlc.setDoOutput( true );
+ urlc.setAllowUserInteraction( false );
+ final PrintStream ps = new PrintStream( urlc.getOutputStream() );
+ //System.out.println( "query: " + query );
+ ps.print( query.trim() );
+ ps.close();
+ final BufferedReader br = new BufferedReader( new InputStreamReader( urlc.getInputStream() ) );
+ final StringBuffer sb = new StringBuffer();
+ String line = null;
+ while ( ( line = br.readLine() ) != null ) {
+ sb.append( line + LINE_SEPARATOR );
+ }
+ br.close();
+ return sb.toString().trim();
+ }
+
+ public static String getResult( final String query ) throws IOException {
+ System.out.println( query );
+ final URL url = new URL( BASE_URL );
+ final URLConnection urlc = url.openConnection();
+ urlc.setDoOutput( true );
+ urlc.setAllowUserInteraction( false );
+ final PrintStream ps = new PrintStream( urlc.getOutputStream() );
+ //System.out.println( "query: " + query );
+ ps.print( query.trim() );
+ ps.close();
+ final BufferedReader br = new BufferedReader( new InputStreamReader( urlc.getInputStream() ) );
+ final StringBuffer sb = new StringBuffer();
+ String line = null;
+ while ( ( line = br.readLine() ) != null ) {
+ sb.append( line + LINE_SEPARATOR );
+ }
+ br.close();
+ return sb.toString().trim();
+ }
+}
--- /dev/null
+// $Id:
+// forester -- software libraries and applications
+// for genomics and evolutionary biology research.
+//
+// Copyright (C) 2010 Christian M Zmasek
+// Copyright (C) 2010 Sanford-Burnham Medical Research Institute
+// 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: www.phylosoft.org/forester
+
+package org.forester.development;
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseMotionAdapter;
+
+import javax.swing.JComponent;
+
+import org.forester.msa.Msa;
+
+public class MsaRenderer extends JComponent {
+
+ private static final long serialVersionUID = -68078011081748093L;
+
+ public static boolean isMouseEventAltered( final MouseEvent event ) {
+ return event.isShiftDown() || event.isAltDown() || event.isControlDown() || event.isAltGraphDown()
+ || event.isMetaDown();
+ }
+ //private PlateDisplayPanel _heatMapPanel;
+ private final int _rows;
+ private final int _columns;
+ private int _wellSize;
+ private AbstractRenderer _wells[][];
+ private double _min;
+ private double _max;
+ private double _mean;
+ private Color _minColor;
+ private Color _maxColor;
+ private Color _meanColor;
+ private boolean _useMean;
+ // private Rubberband _rubberband;
+ private final Msa _msa;
+ private final JComponent _parent;
+
+ public MsaRenderer( final Msa msa, final int unit_size, final JComponent parent ) {
+ _parent = parent;
+ _msa = msa;
+ _rows = _msa.getNumberOfSequences();
+ _columns = _msa.getLength();
+ setWellSize( unit_size );
+ addMouseListeners();
+ initializeWells();
+ //setRubberband( new RubberbandRectangle( this ) );
+ }
+
+ private void addMouseListeners() {
+ addMouseMotionListener( new MouseMotionAdapter() {
+
+ @Override
+ public void mouseDragged( final MouseEvent event ) {
+ // if ( ( ( event.getModifiers() & 0x10 ) != 0 ) && getRubberband().isActive()
+ // && !PlateRenderer.isMouseEventAltered( event ) ) {
+ // getRubberband().stretch( event.getPoint() );
+ // }
+ }
+ } );
+ addMouseListener( new MouseAdapter() {
+
+ @Override
+ public void mouseClicked( final MouseEvent event ) {
+ // if ( ( ( event.getModifiers() & 4 ) != 0 ) || PlateRenderer.isMouseEventAltered( event ) ) {
+ // getInfo( new Rectangle( event.getX(), event.getY(), 1, 1 ) );
+ // }
+ // else {
+ // changeSelected( new Rectangle( event.getX(), event.getY(), 1, 1 ), true );
+ // event.consume();
+ // }
+ }
+
+ @Override
+ public void mousePressed( final MouseEvent event ) {
+ // if ( ( ( event.getModifiers() & 4 ) != 0 ) || PlateRenderer.isMouseEventAltered( event ) ) {
+ // getInfo( new Rectangle( event.getX(), event.getY(), 1, 1 ) );
+ // }
+ // if ( ( ( event.getModifiers() & 0x10 ) != 0 ) && getRubberband().isActive() ) {
+ // getRubberband().anchor( event.getPoint() );
+ // }
+ }
+
+ @Override
+ public void mouseReleased( final MouseEvent event ) {
+ // if ( ( ( event.getModifiers() & 0x10 ) != 0 ) && getRubberband().isActive() ) {
+ // getRubberband().end( event.getPoint() );
+ // rubberbandEnded( getRubberband() );
+ // }
+ }
+ } );
+ }
+
+ public AbstractRenderer getAbstractRenderer( final int row, final int col ) {
+ return _wells[ row ][ col ];
+ }
+
+ public int getColumns() {
+ return _columns;
+ }
+
+ private double getMax() {
+ return _max;
+ }
+
+ private Color getMaxColor() {
+ return _maxColor;
+ }
+
+ private double getMean() {
+ return _mean;
+ }
+
+ private Color getMeanColor() {
+ return _meanColor;
+ }
+
+ private double getMin() {
+ return _min;
+ }
+
+ private Color getMinColor() {
+ return _minColor;
+ }
+
+ @Override
+ public Dimension getPreferredSize() {
+ final int width = ( getWellSize() + 1 ) * ( getColumns() + 1 );
+ final int hight = ( getWellSize() + 1 ) * ( getRows() + 1 ) + 30;
+ return new Dimension( width, hight );
+ }
+
+ public int getRows() {
+ return _rows;
+ }
+
+ // private Rubberband getRubberband() {
+ // return _rubberband;
+ // }
+ private int getWellSize() {
+ return _wellSize;
+ }
+
+ private void initializeWells() {
+ _wells = new AbstractRenderer[ getRows() + 1 ][ getColumns() + 1 ];
+ for( int row = 0; row < getRows(); row++ ) {
+ for( int col = 0; col < getColumns() + 1; col++ ) {
+ AbstractRenderer r;
+ if ( col == getColumns() ) {
+ // r = new LabelRenderer( PlateData.ALPHABET[ row % PlateData.ALPHABET.length ] + "", this );
+ }
+ //else if ( getPlateData().getData( row, col ) == null ) {
+ // r = new WellRenderer( new WellData(), this );
+ // }
+ else {
+ r = new ResidueRenderer( getMsa().getResidueAt( row, col ), this );
+ }
+ // r.setVisible( true );
+ // setAbstractRenderer( r, row, col );
+ }
+ }
+ for( int col = 0; col < getColumns() + 1; col++ ) {
+ // AbstractRenderer r;
+ if ( col == getColumns() ) {
+ // r = new LabelRenderer( "", this );
+ }
+ else {
+ // r = new LabelRenderer( ( col + 1 ) + "", this );
+ }
+ // r.setVisible( true );
+ // setAbstractRenderer( r, getRows(), col );
+ }
+ }
+
+ private Msa getMsa() {
+ return _msa;
+ }
+
+ public void inverseMarkedOfWell( final int well_row, final int well_col ) {
+ final ResidueRenderer rend = ( ResidueRenderer ) getAbstractRenderer( well_row, well_col );
+ if ( rend.isMarked() ) {
+ rend.setIsMarked( false );
+ }
+ else {
+ rend.setIsMarked( true );
+ }
+ }
+
+ private boolean isUseMean() {
+ return _useMean;
+ }
+
+ @Override
+ public void paint( final Graphics g ) {
+ g.setColor( Color.white );
+ // g.setFont( getPlateDisplayPanel().getPlateTitleFont() );
+ // g
+ // .drawString( "Number:" + getPlateData().getName() + " Replicate:"
+ // + ( getPlateData().getReplicateNumber() + 1 ), 10, 20 );
+ for( int row = 0; row < getRows() + 1; row++ ) {
+ for( int col = 0; col < getColumns() + 1; col++ ) {
+ getAbstractRenderer( row, col ).paint( g );
+ }
+ }
+ }
+
+ public void resetWellColors() {
+ for( int row = 0; row < getRows(); row++ ) {
+ for( int col = 0; col < getColumns(); col++ ) {
+ final ResidueRenderer r = ( ResidueRenderer ) getAbstractRenderer( row, col );
+ if ( isUseMean() ) {
+ r.resetWellColor( getMin(), getMax(), getMean(), getMinColor(), getMaxColor(), getMeanColor() );
+ }
+ else {
+ r.resetWellColor( getMin(), getMax(), getMinColor(), getMaxColor() );
+ }
+ }
+ }
+ }
+
+ public void resetWellSize( final int well_size ) {
+ setWellSize( well_size );
+ final int factor = well_size + 0;
+ for( int row = 0; row < getRows() + 1; row++ ) {
+ for( int col = 0; col < getColumns() + 1; col++ ) {
+ final AbstractRenderer r = getAbstractRenderer( row, col );
+ r.setX( 10 + factor * col );
+ r.setY( factor * row + 30 );
+ r.setWellSize( well_size );
+ }
+ }
+ }
+
+ // private void rubberbandEnded( final Rubberband rb ) {
+ // changeSelected( rb.getBounds(), false );
+ // repaint();
+ // }
+ private void setAbstractRenderer( final AbstractRenderer ar, final int row, final int col ) {
+ _wells[ row ][ col ] = ar;
+ }
+
+ public void setFlaggedStatusOfOutlierWells( final boolean set_flagged_to_this ) {
+ for( int row = 0; row < getRows(); row++ ) {
+ for( int col = 0; col < getColumns(); col++ ) {
+ final ResidueRenderer wr = ( ResidueRenderer ) getAbstractRenderer( row, col );
+ // if ( wr.isFlaggedByStatisticalAnalysis() ) {
+ // wr.setIsUserFlagged( set_flagged_to_this );
+ // }
+ }
+ }
+ }
+
+ public void setFlaggedStatusOfSelectedWells( final boolean set_flagged_to_this ) {
+ for( int row = 0; row < getRows(); row++ ) {
+ for( int col = 0; col < getColumns(); col++ ) {
+ final ResidueRenderer wr = ( ResidueRenderer ) getAbstractRenderer( row, col );
+ if ( wr.isSelected() ) {
+ // wr.setIsUserFlagged( set_flagged_to_this );
+ wr.setIsSelected( false );
+ }
+ }
+ }
+ }
+
+ public void setIsFlaggingStatusChangedToFalse() {
+ for( int row = 0; row < getRows(); row++ ) {
+ for( int col = 0; col < getColumns(); col++ ) {
+ final ResidueRenderer wr = ( ResidueRenderer ) getAbstractRenderer( row, col );
+ // wr.setIsFlaggingStatusChanged( false );
+ }
+ }
+ }
+
+ private void setIsSelectedOfAll( final boolean isSelected ) {
+ for( int col = 0; col < getColumns() + 1; col++ ) {
+ setIsSelectedOfColumn( col, isSelected );
+ }
+ }
+
+ private void setIsSelectedOfColumn( final int column, final boolean isSelected ) {
+ for( int row = 0; row < getRows() + 1; row++ ) {
+ getAbstractRenderer( row, column ).setIsSelected( isSelected );
+ }
+ }
+
+ private void setIsSelectedOfRow( final int row, final boolean isSelected ) {
+ for( int col = 0; col < getColumns() + 1; col++ ) {
+ getAbstractRenderer( row, col ).setIsSelected( isSelected );
+ }
+ }
+
+ private void setIsSelectedOfRowAlternating( final int row, final boolean even ) {
+ boolean selected = even;
+ for( int col = 0; col < getColumns(); col++ ) {
+ getAbstractRenderer( row, col ).setIsSelected( selected );
+ selected = !selected;
+ }
+ }
+
+ private void setIsSelectedToQuarter( final int quarter ) {
+ boolean evenRow = false;
+ boolean evenColumn = false;
+ if ( quarter <= 1 ) {
+ evenRow = true;
+ evenColumn = true;
+ }
+ else if ( quarter == 2 ) {
+ evenColumn = true;
+ }
+ else if ( quarter == 3 ) {
+ evenRow = true;
+ }
+ for( int row = 0; row < getRows(); row++ ) {
+ if ( evenColumn ) {
+ setIsSelectedOfRowAlternating( row, evenRow );
+ }
+ else {
+ setIsSelectedOfRow( row, false );
+ }
+ evenColumn = !evenColumn;
+ }
+ }
+
+ public void setMarkedOfAllWellsToFalse() {
+ for( int row = 0; row < getRows(); row++ ) {
+ for( int col = 0; col < getColumns(); col++ ) {
+ final ResidueRenderer wr = ( ResidueRenderer ) getAbstractRenderer( row, col );
+ // rend.setIsMarked( false );
+ }
+ }
+ }
+
+ public void setMax( final double max ) {
+ _max = max;
+ }
+
+ void setMaxColor( final Color maxColor ) {
+ _maxColor = maxColor;
+ }
+
+ void setMean( final double mean ) {
+ _mean = mean;
+ }
+
+ public void setMeanColor( final Color meanColor ) {
+ _meanColor = meanColor;
+ }
+
+ public void setMin( final double min ) {
+ _min = min;
+ }
+
+ void setMinColor( final Color minColor ) {
+ _minColor = minColor;
+ }
+
+ // private void setRubberband( final Rubberband rb ) {
+ // if ( _rubberband != null ) {
+ // _rubberband.setActive( false );
+ // }
+ // _rubberband = rb;
+ // if ( _rubberband != null ) {
+ // _rubberband.setComponent( this );
+ // _rubberband.setActive( true );
+ // }
+ // }
+ public void setUseMean( final boolean useMean ) {
+ _useMean = useMean;
+ }
+
+ private void setWellSize( final int wellSize ) {
+ _wellSize = wellSize;
+ }
+
+ public void unSelectUnMarkAll() {
+ for( int row = 0; row < getRows(); row++ ) {
+ for( int col = 0; col < getColumns(); col++ ) {
+ final ResidueRenderer wr = ( ResidueRenderer ) getAbstractRenderer( row, col );
+ wr.setIsSelected( false );
+ wr.setIsMarked( false );
+ }
+ }
+ }
+}
--- /dev/null
+
+package org.forester.development;
+
+import java.util.Random;
+
+public class RandomThing {
+
+ public static void main( final String[] args ) {
+ final Random rg = new Random();
+ for( int i = 0; i < 200; i++ ) {
+ for( int j = 0; j < 30; j++ ) {
+ System.out.print( "\t" + rg.nextFloat() );
+ }
+ System.out.println();
+ }
+ }
+}
--- /dev/null
+// $Id:
+// forester -- software libraries and applications
+// for genomics and evolutionary biology research.
+//
+// Copyright (C) 2010 Christian M Zmasek
+// Copyright (C) 2010 Sanford-Burnham Medical Research Institute
+// 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: www.phylosoft.org/forester
+
+package org.forester.development;
+
+import java.awt.Color;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.RenderingHints;
+
+public class ResidueRenderer extends AbstractRenderer {
+
+ static final Color EMPTY_COLOR = new Color( 250, 0, 250 );
+ static final Color POSITIVE_COLOR = new Color( 250, 0, 250 );
+ static final Color NEGATIVE_COLOR = new Color( 250, 0, 250 );
+ static final Color NULL_COLOR = new Color( 50, 50, 50 );
+ static final int DISTANCE_OVAL_BORDER = 1;
+ static final int SIZE_LIMIT = 7;
+ /**
+ *
+ */
+ private static final long serialVersionUID = -2331160296913478874L;
+ private final char _value;
+ private Color _wellColor;
+ private boolean _isMarked;
+ private boolean _isSelected;
+ private final MsaRenderer _parentPlateRenderer;
+
+ public ResidueRenderer( final char value, final MsaRenderer parentPlateRenderer ) {
+ _value = value;
+ _parentPlateRenderer = parentPlateRenderer;
+ setIsSelected( false );
+ setIsMarked( false );
+ setStatus( ( byte ) 0 );
+ }
+
+ private double calcFactor( final double min, final double max ) {
+ return ( max - min ) / 255D;
+ }
+
+ private Color calcWellColor( double value,
+ final double min,
+ final double max,
+ final Color minColor,
+ final Color maxColor ) {
+ if ( value < min ) {
+ value = min;
+ }
+ if ( value > max ) {
+ value = max;
+ }
+ final double x = ( 255D * ( value - min ) ) / ( max - min );
+ final int red = ( int ) ( minColor.getRed() + x * calcFactor( minColor.getRed(), maxColor.getRed() ) );
+ final int green = ( int ) ( minColor.getGreen() + x * calcFactor( minColor.getGreen(), maxColor.getGreen() ) );
+ final int blue = ( int ) ( minColor.getBlue() + x * calcFactor( minColor.getBlue(), maxColor.getBlue() ) );
+ return new Color( red, green, blue );
+ }
+
+ private Color calcWellColor( double value,
+ final double min,
+ final double max,
+ final double mean,
+ final Color minColor,
+ final Color maxColor,
+ final Color meanColor ) {
+ // if ( isEmpty() ) {
+ // return ResidueRenderer.NULL_COLOR;
+ // }
+ if ( meanColor == null ) {
+ return calcWellColor( value, min, max, minColor, maxColor );
+ }
+ if ( value < min ) {
+ value = min;
+ }
+ if ( value > max ) {
+ value = max;
+ }
+ if ( value < mean ) {
+ final double x = ( 255D * ( value - min ) ) / ( mean - min );
+ final int red = ( int ) ( minColor.getRed() + x * calcFactor( minColor.getRed(), meanColor.getRed() ) );
+ final int green = ( int ) ( minColor.getGreen() + x
+ * calcFactor( minColor.getGreen(), meanColor.getGreen() ) );
+ final int blue = ( int ) ( minColor.getBlue() + x * calcFactor( minColor.getBlue(), meanColor.getBlue() ) );
+ return new Color( red, green, blue );
+ }
+ if ( value > mean ) {
+ final double x = ( 255D * ( value - mean ) ) / ( max - mean );
+ final int red = ( int ) ( meanColor.getRed() + x * calcFactor( meanColor.getRed(), maxColor.getRed() ) );
+ final int green = ( int ) ( meanColor.getGreen() + x
+ * calcFactor( meanColor.getGreen(), maxColor.getGreen() ) );
+ final int blue = ( int ) ( meanColor.getBlue() + x * calcFactor( meanColor.getBlue(), maxColor.getBlue() ) );
+ return new Color( red, green, blue );
+ }
+ else {
+ return meanColor;
+ }
+ }
+
+ public double getDataValue() {
+ return _value;
+ }
+
+ @Override
+ public MsaRenderer getParentPlateRenderer() {
+ return _parentPlateRenderer;
+ }
+
+ public Color getWellColor() {
+ return _wellColor;
+ }
+
+ public boolean isMarked() {
+ return _isMarked;
+ }
+
+ @Override
+ public boolean isSelected() {
+ return _isSelected;
+ }
+
+ @Override
+ public void paint( final Graphics g ) {
+ final int width = getWellSize() - 1;
+ final int width_ = width - 1;
+ final int width__ = ( width_ - 1 ) + 1;
+ final int width__s = width__ - 2;
+ final int x_ = getX() + 1;
+ final int y_ = getY() + 1;
+ // final PlateDisplayPanel hmp = getParentPlateRenderer()
+ // .getPlateDisplayPanel();
+ // boolean draw_circle = hmp.isDrawCircle()
+ // || ( !hmp.isDrawCircle() && !hmp.isDrawSquare() && ( width > 7 ) );
+ // final boolean show_user_flags = _parentPlateRenderer
+ // .getPlateDisplayPanel().showUserFlagsCheckBox.isSelected();
+ // final boolean show_outlier_flags = _parentPlateRenderer
+ // .getPlateDisplayPanel().showOutliersCheckBox.isSelected();
+ // final boolean show_hit_picks = _parentPlateRenderer
+ // .getPlateDisplayPanel().showHitPicksCheckBox.isSelected();
+ // final boolean show_confirmed_hits = _parentPlateRenderer
+ // .getPlateDisplayPanel().showConfirmedHitsCheckBox.isSelected();
+ final Graphics2D g2 = ( Graphics2D ) g;
+ g2.setRenderingHint( RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_SPEED );
+ if ( isMarked() ) {
+ g2.setColor( AbstractRenderer.MARKED_COLOR );
+ }
+ // else if ( !draw_circle && isSelected() ) {
+ // g2.setColor( AbstractRenderer.SELECTED_COLOR );
+ // }
+ else {
+ g2.setColor( AbstractRenderer.DEFAULT_COLOR );
+ }
+ g2.drawRect( getX(), getY(), width, width );
+ // if ( draw_circle ) {
+ // if ( isSelected() && isMarked() ) {
+ // g2.setColor( AbstractRenderer.MARKED_COLOR );
+ // }
+ // else if ( isSelected() ) {
+ // g2.setColor( AbstractRenderer.SELECTED_COLOR );
+ // }
+ // else {
+ // g2.setColor( AbstractRenderer.DEFAULT_COLOR );
+ // }
+ // g2.fillRect( x_, y_, width_, width_ );
+ // }
+ g2.setColor( getWellColor() );
+ // if ( draw_circle ) {
+ // g2.setRenderingHint( RenderingHints.KEY_ANTIALIASING,
+ // RenderingHints.VALUE_ANTIALIAS_ON );
+ // if ( isSelected() && ( width > 6 ) ) {
+ // g2.fillOval( getX() + 2, getY() + 2, width__s, width__s );
+ // }
+ // else if ( width < 5 ) {
+ // g2.fillOval( ( getX() + 1 ) - 1, ( getY() + 1 ) - 1,
+ // width__ + 2, width__ + 2 );
+ // }
+ // else {
+ // g2.fillOval( getX() + 1, getY() + 1, width__, width__ );
+ // }
+ // }
+ if ( isMarked() || isSelected() ) {
+ g2.fillRect( getX() + 1, getY() + 1, width_, width_ );
+ }
+ else {
+ g2.fillRect( ( getX() + 1 ) - 1, ( getY() + 1 ) - 1, width_ + 2, width_ + 2 );
+ }
+ }
+
+ public void resetWellColor( final double min, final double max, final Color minColor, final Color maxColor ) {
+ setWellColor( calcWellColor( getDataValue(), min, max, minColor, maxColor ) );
+ }
+
+ public void resetWellColor( final double min,
+ final double max,
+ final double mean,
+ final Color minColor,
+ final Color maxColor,
+ final Color meanColor ) {
+ setWellColor( calcWellColor( getDataValue(), min, max, mean, minColor, maxColor, meanColor ) );
+ }
+
+ public void setIsMarked( final boolean isMarked ) {
+ _isMarked = isMarked;
+ }
+
+ @Override
+ public void setIsSelected( final boolean isSelected ) {
+ _isSelected = isSelected;
+ }
+
+ private void setWellColor( final Color wellColor ) {
+ _wellColor = wellColor;
+ }
+}
--- /dev/null
+// $Id:
+// FORESTER -- software libraries and applications
+// for evolutionary biology research and applications.
+//
+// Copyright (C) 2008-2009 Christian M. Zmasek
+// Copyright (C) 2008-2009 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: www.phylosoft.org/forester
+
+package org.forester.development;
+
+import java.io.File;
+import java.util.Date;
+import java.util.Locale;
+
+import org.forester.util.ForesterUtil;
+
+/*
+ * *
+ */
+public class Test {
+
+ private final static String PATH_TO_TEST_DATA = System.getProperty( "user.dir" ) + ForesterUtil.getFileSeparator()
+ + "test_data" + ForesterUtil.getFileSeparator();
+
+ public static void main( final String[] args ) {
+ System.out.println( "[Java version: " + ForesterUtil.JAVA_VERSION + " " + ForesterUtil.JAVA_VENDOR + "]" );
+ System.out.println( "[OS: " + ForesterUtil.OS_NAME + " " + ForesterUtil.OS_ARCH + " " + ForesterUtil.OS_VERSION
+ + "]" );
+ Locale.setDefault( Locale.US );
+ System.out.println( "[Locale: " + Locale.getDefault() + "]" );
+ final int failed = 0;
+ final int succeeded = 0;
+ System.out.print( "[Test if directory with files for testing exists/is readable: " );
+ if ( Test.testDir( PATH_TO_TEST_DATA ) ) {
+ System.out.println( "OK.]" );
+ }
+ else {
+ System.out.println( "could not find/read from directory \"" + PATH_TO_TEST_DATA + "\".]" );
+ System.out.println( "Testing aborted." );
+ System.exit( -1 );
+ }
+ final long start_time = new Date().getTime();
+ System.out.println( "\nTime requirement: " + ( new Date().getTime() - start_time ) + "ms." );
+ System.out.println();
+ System.out.println( "Successful tests: " + succeeded );
+ System.out.println( "Failed tests: " + failed );
+ System.out.println();
+ if ( failed < 1 ) {
+ System.out.println( "OK." );
+ }
+ else {
+ System.out.println( "Not OK." );
+ }
+ }
+
+ private static boolean testDir( final String file ) {
+ try {
+ final File f = new File( file );
+ if ( !f.exists() ) {
+ return false;
+ }
+ if ( !f.isDirectory() ) {
+ return false;
+ }
+ if ( !f.canRead() ) {
+ return false;
+ }
+ }
+ catch ( final Exception e ) {
+ return false;
+ }
+ return true;
+ }
+}
--- /dev/null
+// $Id:
+// $
+//
+// FORESTER -- software libraries and applications
+// for evolutionary biology research and applications.
+//
+// Copyright (C) 2008-2009 Christian M. Zmasek
+// Copyright (C) 2008-2009 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: www.phylosoft.org/forester
+
+package org.forester.evoinference;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.StringWriter;
+import java.util.Date;
+import java.util.List;
+
+import org.forester.evoinference.distance.NeighborJoining;
+import org.forester.evoinference.distance.PairwiseDistanceCalculator;
+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.evoinference.matrix.character.CharacterStateMatrix.GainLossStates;
+import org.forester.evoinference.matrix.distance.BasicSymmetricalDistanceMatrix;
+import org.forester.evoinference.matrix.distance.DistanceMatrix;
+import org.forester.evoinference.parsimony.DolloParsimony;
+import org.forester.evoinference.parsimony.FitchParsimony;
+import org.forester.io.parsers.GeneralMsaParser;
+import org.forester.io.parsers.SymmetricalDistanceMatrixParser;
+import org.forester.io.parsers.nhx.NHXParser;
+import org.forester.msa.Msa;
+import org.forester.phylogeny.Phylogeny;
+import org.forester.phylogeny.factories.ParserBasedPhylogenyFactory;
+import org.forester.phylogeny.factories.PhylogenyFactory;
+import org.forester.util.ForesterUtil;
+
+public class TestPhylogenyReconstruction {
+
+ private final static double ZERO_DIFF = 1.0E-9;
+ private final static boolean TIME = false;
+
+ public static boolean isEqual( final double a, final double b ) {
+ return ( ( Math.abs( a - b ) ) < ZERO_DIFF );
+ }
+
+ public static void main( final String[] args ) {
+ timeNeighborJoining();
+ }
+
+ public static boolean test( final File test_dir ) {
+ System.out.print( " Basic symmetrical distance matrix: " );
+ if ( !testBasicSymmetricalDistanceMatrix() ) {
+ System.out.println( "failed." );
+ return false;
+ }
+ System.out.println( "OK." );
+ System.out.print( " Basic character state matrix: " );
+ if ( !testBasicCharacterStateMatrix() ) {
+ System.out.println( "failed." );
+ return false;
+ }
+ System.out.println( "OK." );
+ System.out.print( " Symmetrical distance matrix parser: " );
+ if ( !testSymmetricalDistanceMatrixParser() ) {
+ System.out.println( "failed." );
+ return false;
+ }
+ System.out.println( "OK." );
+ System.out.print( " Distance Calculation: " );
+ if ( !testDistanceCalculationMethods( test_dir ) ) {
+ System.out.println( "failed." );
+ return false;
+ }
+ System.out.println( "OK." );
+ System.out.print( " Neighbor Joining: " );
+ if ( !testNeighborJoining() ) {
+ System.out.println( "failed." );
+ return false;
+ }
+ System.out.println( "OK." );
+ System.out.print( " Dollo Parsimony: " );
+ if ( !testDolloParsimony() ) {
+ System.out.println( "failed." );
+ return false;
+ }
+ System.out.println( "OK." );
+ System.out.print( " Dollo Parsimony on non binary trees: " );
+ if ( !testDolloParsimonyOnNonBinaryTree() ) {
+ System.out.println( "failed." );
+ return false;
+ }
+ System.out.println( "OK." );
+ System.out.print( " Fitch Parsimony: " );
+ if ( !testFitchParsimony() ) {
+ System.out.println( "failed." );
+ return false;
+ }
+ System.out.println( "OK." );
+ return true;
+ }
+
+ private static boolean testDistanceCalculationMethods( final File test_dir ) {
+ try {
+ final Msa msa0 = GeneralMsaParser.parse( new FileInputStream( test_dir + ForesterUtil.FILE_SEPARATOR
+ + "bcl.aln" ) );
+ final BasicSymmetricalDistanceMatrix pwd0 = PairwiseDistanceCalculator.calcKimuraDistances( msa0 );
+ if ( pwd0.getSize() != 120 ) {
+ return false;
+ }
+ for( int i = 0; i < pwd0.getSize(); ++i ) {
+ if ( !isEqual( pwd0.getValue( i, i ), 0.0 ) ) {
+ return false;
+ }
+ }
+ }
+ catch ( final Exception e ) {
+ e.printStackTrace( System.out );
+ return false;
+ }
+ return true;
+ }
+
+ private static boolean testBasicCharacterStateMatrix() {
+ try {
+ final CharacterStateMatrix<String> matrix_0 = new BasicCharacterStateMatrix<String>( 4, 8 );
+ final CharacterStateMatrix<String> matrix_00 = new BasicCharacterStateMatrix<String>( 4, 8 );
+ matrix_0.setIdentifier( 0, "A" );
+ matrix_0.setIdentifier( 1, "B" );
+ matrix_0.setIdentifier( 2, "C" );
+ matrix_0.setIdentifier( 3, "D" );
+ matrix_0.setCharacter( 0, "0" );
+ matrix_0.setCharacter( 1, "1" );
+ matrix_0.setCharacter( 2, "2" );
+ matrix_0.setCharacter( 3, "3" );
+ matrix_0.setCharacter( 4, "4" );
+ matrix_0.setCharacter( 5, "5" );
+ matrix_0.setCharacter( 6, "6" );
+ matrix_0.setCharacter( 7, "7" );
+ matrix_00.setIdentifier( 0, "A" );
+ matrix_00.setIdentifier( 1, "B" );
+ matrix_00.setIdentifier( 2, "C" );
+ matrix_00.setIdentifier( 3, "D" );
+ matrix_00.setCharacter( 3, "3" );
+ matrix_00.setCharacter( 4, "4" );
+ if ( !matrix_0.getCharacter( 1 ).equals( "1" ) ) {
+ return false;
+ }
+ if ( !matrix_0.getIdentifier( 0 ).equals( "A" ) ) {
+ return false;
+ }
+ matrix_0.setState( 0, 0, "00" );
+ matrix_00.setState( 0, 0, "00" );
+ if ( !matrix_0.getState( 0, 0 ).equals( "00" ) ) {
+ return false;
+ }
+ matrix_0.setState( 0, 1, "01" );
+ matrix_00.setState( 0, 1, "01" );
+ if ( !matrix_0.getState( 0, 1 ).equals( "01" ) ) {
+ return false;
+ }
+ matrix_0.setState( 1, 1, "11" );
+ matrix_00.setState( 1, 1, "11" );
+ if ( !matrix_0.getState( 1, 1 ).equals( "11" ) ) {
+ return false;
+ }
+ matrix_0.setState( 1, 0, "10" );
+ matrix_00.setState( 1, 0, "10" );
+ if ( !matrix_0.getState( 1, 0 ).equals( "10" ) ) {
+ return false;
+ }
+ matrix_0.setState( 1, 2, "12" );
+ matrix_00.setState( 1, 2, "12" );
+ if ( !matrix_0.getState( 1, 2 ).equals( "12" ) ) {
+ return false;
+ }
+ matrix_0.setState( 3, 7, "37" );
+ matrix_00.setState( 3, 7, "37" );
+ if ( !matrix_0.getState( 3, 7 ).equals( "37" ) ) {
+ return false;
+ }
+ matrix_0.setState( 2, 6, "26" );
+ matrix_00.setState( 2, 6, "26" );
+ if ( !matrix_0.getState( 2, 6 ).equals( "26" ) ) {
+ return false;
+ }
+ matrix_0.setState( "D", "3", "33" );
+ matrix_00.setState( "D", "3", "33" );
+ if ( !matrix_0.getState( 3, 3 ).equals( "33" ) ) {
+ return false;
+ }
+ if ( !matrix_0.getState( "D", "3" ).equals( "33" ) ) {
+ return false;
+ }
+ matrix_0.setState( "C", "4", "24" );
+ matrix_00.setState( "C", "4", "24" );
+ if ( !matrix_0.getState( 2, 4 ).equals( "24" ) ) {
+ return false;
+ }
+ if ( !matrix_0.getState( "C", "4" ).equals( "24" ) ) {
+ return false;
+ }
+ if ( matrix_0.isEmpty() ) {
+ return false;
+ }
+ if ( matrix_0.getNumberOfIdentifiers() != 4 ) {
+ return false;
+ }
+ if ( matrix_0.getNumberOfCharacters() != 8 ) {
+ return false;
+ }
+ if ( !matrix_0.equals( matrix_0 ) ) {
+ return false;
+ }
+ if ( !matrix_0.equals( matrix_00 ) ) {
+ return false;
+ }
+ matrix_00.setState( "C", "4", "123" );
+ if ( matrix_0.equals( matrix_00 ) ) {
+ return false;
+ }
+ final Integer[][] ints = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } };
+ final CharacterStateMatrix<Integer> matrix_000 = new BasicCharacterStateMatrix<Integer>( ints );
+ matrix_000.toString();
+ if ( matrix_000.getNumberOfCharacters() != 4 ) {
+ return false;
+ }
+ if ( matrix_000.getNumberOfIdentifiers() != 3 ) {
+ return false;
+ }
+ if ( matrix_000.getState( 0, 1 ) != 2 ) {
+ return false;
+ }
+ if ( matrix_000.getState( 2, 3 ) != 12 ) {
+ return false;
+ }
+ final Integer[][] ints0 = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } };
+ final CharacterStateMatrix<Integer> matrix_0000 = new BasicCharacterStateMatrix<Integer>( ints0 );
+ if ( !matrix_000.equals( matrix_0000 ) ) {
+ return false;
+ }
+ final Integer[][] ints00 = { { 1, 2, 3, -4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } };
+ final CharacterStateMatrix<Integer> matrix_00000 = new BasicCharacterStateMatrix<Integer>( ints00 );
+ if ( matrix_000.equals( matrix_00000 ) ) {
+ return false;
+ }
+ final CharacterStateMatrix<String> clone0 = matrix_0.copy();
+ final CharacterStateMatrix<String> clone00 = matrix_00.copy();
+ if ( !clone0.equals( matrix_0 ) ) {
+ return false;
+ }
+ if ( !clone00.equals( matrix_00 ) ) {
+ return false;
+ }
+ if ( clone00.equals( clone0 ) ) {
+ return false;
+ }
+ final CharacterStateMatrix<String> pivot0 = matrix_0.pivot();
+ final CharacterStateMatrix<String> pivot00 = matrix_00.pivot();
+ if ( !pivot0.getState( 1, 0 ).equals( "01" ) ) {
+ return false;
+ }
+ if ( !pivot0.getState( 6, 2 ).equals( "26" ) ) {
+ return false;
+ }
+ if ( !matrix_0.getState( 2, 6 ).equals( "26" ) ) {
+ return false;
+ }
+ final CharacterStateMatrix<String> pivotpivot00 = pivot00.pivot();
+ if ( !pivotpivot00.equals( matrix_00 ) ) {
+ return false;
+ }
+ final CharacterStateMatrix<BinaryStates> nex = new BasicCharacterStateMatrix<BinaryStates>( 4, 3 );
+ nex.setIdentifier( 0, "amphioxus" );
+ nex.setIdentifier( 1, "sponge" );
+ nex.setIdentifier( 2, "sea_anemone" );
+ nex.setIdentifier( 3, "cobra" );
+ nex.setCharacter( 0, "notch" );
+ nex.setCharacter( 1, "homeobox" );
+ nex.setCharacter( 2, "wnt" );
+ nex.setState( 0, 0, BinaryStates.ABSENT );
+ nex.setState( 0, 1, BinaryStates.ABSENT );
+ nex.setState( 0, 2, BinaryStates.ABSENT );
+ nex.setState( 1, 0, BinaryStates.PRESENT );
+ nex.setState( 1, 1, BinaryStates.PRESENT );
+ nex.setState( 1, 2, BinaryStates.ABSENT );
+ nex.setState( 2, 0, BinaryStates.PRESENT );
+ nex.setState( 2, 1, BinaryStates.PRESENT );
+ nex.setState( 2, 2, BinaryStates.PRESENT );
+ nex.setState( 3, 0, BinaryStates.PRESENT );
+ nex.setState( 3, 1, BinaryStates.ABSENT );
+ nex.setState( 3, 2, BinaryStates.ABSENT );
+ StringWriter w = new StringWriter();
+ nex.toWriter( w, CharacterStateMatrix.Format.NEXUS_BINARY );
+ //System.out.println( w.getBuffer().toString() );
+ w = new StringWriter();
+ nex.pivot().toWriter( w, CharacterStateMatrix.Format.NEXUS_BINARY );
+ //System.out.println( w.getBuffer().toString() );
+ }
+ catch ( final Exception e ) {
+ e.printStackTrace( System.out );
+ return false;
+ }
+ return true;
+ }
+
+ private static boolean testBasicSymmetricalDistanceMatrix() {
+ try {
+ final DistanceMatrix matrix_0 = new BasicSymmetricalDistanceMatrix( 4 );
+ matrix_0.setIdentifier( 0, "A" );
+ matrix_0.setIdentifier( 1, "B" );
+ matrix_0.setIdentifier( 2, "C" );
+ matrix_0.setIdentifier( 3, "0123456789012" );
+ matrix_0.setValue( 1, 0, 0.00001 );
+ matrix_0.setValue( 0, 2, 0.0000009 );
+ matrix_0.setValue( 3, 0, 3.0 );
+ matrix_0.setValue( 1, 2, 4.0 );
+ matrix_0.setValue( 3, 1, 5.0 );
+ matrix_0.setValue( 2, 3, 6.0 );
+ if ( !matrix_0.getIdentifier( 0 ).equals( "A" ) ) {
+ return false;
+ }
+ if ( !matrix_0.getIdentifier( 1 ).equals( "B" ) ) {
+ return false;
+ }
+ if ( !matrix_0.getIdentifier( 2 ).equals( "C" ) ) {
+ return false;
+ }
+ if ( !matrix_0.getIdentifier( 3 ).equals( "0123456789012" ) ) {
+ return false;
+ }
+ if ( matrix_0.getSize() != 4 ) {
+ return false;
+ }
+ if ( !isEqual( matrix_0.getValue( 0, 0 ), 0.0 ) ) {
+ return false;
+ }
+ if ( !isEqual( matrix_0.getValue( 3, 3 ), 0.0 ) ) {
+ return false;
+ }
+ if ( !isEqual( matrix_0.getValue( 0, 1 ), 0.00001 ) ) {
+ return false;
+ }
+ if ( !isEqual( matrix_0.getValue( 0, 2 ), 0.0000009 ) ) {
+ return false;
+ }
+ if ( !isEqual( matrix_0.getValue( 0, 3 ), 3 ) ) {
+ return false;
+ }
+ if ( !isEqual( matrix_0.getValue( 1, 0 ), 0.00001 ) ) {
+ return false;
+ }
+ if ( !isEqual( matrix_0.getValue( 1, 2 ), 4 ) ) {
+ return false;
+ }
+ if ( !isEqual( matrix_0.getValue( 1, 3 ), 5 ) ) {
+ return false;
+ }
+ if ( !isEqual( matrix_0.getValue( 2, 0 ), 0.0000009 ) ) {
+ return false;
+ }
+ if ( !isEqual( matrix_0.getValue( 2, 1 ), 4 ) ) {
+ return false;
+ }
+ if ( !isEqual( matrix_0.getValue( 2, 3 ), 6 ) ) {
+ return false;
+ }
+ if ( !isEqual( matrix_0.getValue( 3, 0 ), 3 ) ) {
+ return false;
+ }
+ if ( !isEqual( matrix_0.getValue( 3, 1 ), 5 ) ) {
+ return false;
+ }
+ if ( !isEqual( matrix_0.getValue( 3, 2 ), 6 ) ) {
+ return false;
+ }
+ final StringBuffer matrix_0_phylip = new StringBuffer();
+ matrix_0_phylip.append( " 4" );
+ matrix_0_phylip.append( ForesterUtil.LINE_SEPARATOR );
+ matrix_0_phylip.append( "A 0.000000 0.000010 0.000001 3.000000" );
+ matrix_0_phylip.append( ForesterUtil.LINE_SEPARATOR );
+ matrix_0_phylip.append( "B 0.000010 0.000000 4.000000 5.000000" );
+ matrix_0_phylip.append( ForesterUtil.LINE_SEPARATOR );
+ matrix_0_phylip.append( "C 0.000001 4.000000 0.000000 6.000000" );
+ matrix_0_phylip.append( ForesterUtil.LINE_SEPARATOR );
+ matrix_0_phylip.append( "0123456789 3.000000 5.000000 6.000000 0.000000" );
+ if ( !matrix_0_phylip.toString()
+ .equals( matrix_0.toStringBuffer( DistanceMatrix.Format.PHYLIP ).toString() ) ) {
+ return false;
+ }
+ }
+ catch ( final Exception e ) {
+ e.printStackTrace( System.out );
+ return false;
+ }
+ return true;
+ }
+
+ private static boolean testDolloParsimony() {
+ try {
+ final BinaryStates PRESENT = BinaryStates.PRESENT;
+ final BinaryStates ABSENT = BinaryStates.ABSENT;
+ final GainLossStates UNCHANGED_PRESENT = GainLossStates.UNCHANGED_PRESENT;
+ final DolloParsimony dollo1 = DolloParsimony.createInstance();
+ final PhylogenyFactory factory1 = ParserBasedPhylogenyFactory.getInstance();
+ final String p1_str = "((((((a,b)ab,c)ac,d)ad,(e,f)ef)af,(g,h)gh)ah,i)r";
+ final Phylogeny p1 = factory1.create( p1_str, new NHXParser() )[ 0 ];
+ CharacterStateMatrix<CharacterStateMatrix.BinaryStates> m1 = new BasicCharacterStateMatrix<CharacterStateMatrix.BinaryStates>( 9,
+ 1 );
+ m1.setIdentifier( 0, "a" );
+ m1.setIdentifier( 1, "b" );
+ m1.setIdentifier( 2, "c" );
+ m1.setIdentifier( 3, "d" );
+ m1.setIdentifier( 4, "e" );
+ m1.setIdentifier( 5, "f" );
+ m1.setIdentifier( 6, "g" );
+ m1.setIdentifier( 7, "h" );
+ m1.setIdentifier( 8, "i" );
+ m1.setCharacter( 0, "0" );
+ m1.setState( "a", "0", PRESENT );
+ m1.setState( "b", "0", ABSENT );
+ m1.setState( "c", "0", PRESENT );
+ m1.setState( "d", "0", ABSENT );
+ m1.setState( "e", "0", ABSENT );
+ m1.setState( "f", "0", ABSENT );
+ m1.setState( "g", "0", ABSENT );
+ m1.setState( "h", "0", ABSENT );
+ m1.setState( "i", "0", ABSENT );
+ dollo1.execute( p1, m1 );
+ if ( dollo1.getTotalGains() != 1 ) {
+ return false;
+ }
+ if ( dollo1.getTotalLosses() != 1 ) {
+ return false;
+ }
+ if ( dollo1.getTotalUnchanged() != 15 ) {
+ return false;
+ }
+ m1.setState( "b", "0", PRESENT );
+ dollo1.execute( p1, m1 );
+ if ( dollo1.getTotalGains() != 1 ) {
+ return false;
+ }
+ if ( dollo1.getTotalLosses() != 0 ) {
+ return false;
+ }
+ if ( dollo1.getTotalUnchanged() != 16 ) {
+ return false;
+ }
+ m1.setState( "b", "0", ABSENT );
+ m1.setState( "e", "0", PRESENT );
+ dollo1.execute( p1, m1 );
+ if ( dollo1.getTotalGains() != 1 ) {
+ return false;
+ }
+ if ( dollo1.getTotalLosses() != 3 ) {
+ return false;
+ }
+ if ( dollo1.getTotalUnchanged() != 13 ) {
+ return false;
+ }
+ m1.setState( "a", "0", ABSENT );
+ m1.setState( "c", "0", ABSENT );
+ m1.setState( "g", "0", PRESENT );
+ dollo1.setReturnInternalStates( true );
+ dollo1.setReturnGainLossMatrix( true );
+ dollo1.execute( p1, m1 );
+ if ( dollo1.getTotalGains() != 1 ) {
+ return false;
+ }
+ if ( dollo1.getTotalLosses() != 3 ) {
+ return false;
+ }
+ if ( dollo1.getTotalUnchanged() != 13 ) {
+ return false;
+ }
+ final DolloParsimony dollo2 = DolloParsimony.createInstance();
+ final PhylogenyFactory factory2 = ParserBasedPhylogenyFactory.getInstance();
+ final String p2_str = "((((((a,b)ab,c)ac,d)ad,(e,f)ef)af,(g,h,i)gi)ai,((j,k,l)jl,(m,n,o)mo,(p,q,r)pr)jr)root";
+ final Phylogeny p2 = factory2.create( p2_str, new NHXParser() )[ 0 ];
+ final CharacterStateMatrix<CharacterStateMatrix.BinaryStates> m2 = new BasicCharacterStateMatrix<CharacterStateMatrix.BinaryStates>( 18,
+ 4 );
+ m2.setIdentifier( 0, "a" );
+ m2.setIdentifier( 1, "b" );
+ m2.setIdentifier( 2, "c" );
+ m2.setIdentifier( 3, "d" );
+ m2.setIdentifier( 4, "e" );
+ m2.setIdentifier( 5, "f" );
+ m2.setIdentifier( 6, "g" );
+ m2.setIdentifier( 7, "h" );
+ m2.setIdentifier( 8, "i" );
+ m2.setIdentifier( 9, "j" );
+ m2.setIdentifier( 10, "k" );
+ m2.setIdentifier( 11, "l" );
+ m2.setIdentifier( 12, "m" );
+ m2.setIdentifier( 13, "n" );
+ m2.setIdentifier( 14, "o" );
+ m2.setIdentifier( 15, "p" );
+ m2.setIdentifier( 16, "q" );
+ m2.setIdentifier( 17, "r" );
+ m2.setCharacter( 0, "0" );
+ m2.setCharacter( 1, "1" );
+ m2.setCharacter( 2, "2" );
+ m2.setCharacter( 3, "3" );
+ m2.setState( "a", "0", PRESENT );
+ m2.setState( "b", "0", ABSENT );
+ m2.setState( "c", "0", PRESENT );
+ m2.setState( "d", "0", ABSENT );
+ m2.setState( "e", "0", ABSENT );
+ m2.setState( "f", "0", ABSENT );
+ m2.setState( "g", "0", ABSENT );
+ m2.setState( "h", "0", ABSENT );
+ m2.setState( "i", "0", ABSENT );
+ m2.setState( "j", "0", ABSENT );
+ m2.setState( "k", "0", ABSENT );
+ m2.setState( "l", "0", ABSENT );
+ m2.setState( "m", "0", ABSENT );
+ m2.setState( "n", "0", ABSENT );
+ m2.setState( "o", "0", ABSENT );
+ m2.setState( "p", "0", ABSENT );
+ m2.setState( "q", "0", ABSENT );
+ m2.setState( "r", "0", ABSENT );
+ m2.setState( "a", "1", PRESENT );
+ m2.setState( "b", "1", ABSENT );
+ m2.setState( "c", "1", PRESENT );
+ m2.setState( "d", "1", ABSENT );
+ m2.setState( "e", "1", ABSENT );
+ m2.setState( "f", "1", ABSENT );
+ m2.setState( "g", "1", PRESENT );
+ m2.setState( "h", "1", ABSENT );
+ m2.setState( "i", "1", ABSENT );
+ m2.setState( "j", "1", PRESENT );
+ m2.setState( "k", "1", ABSENT );
+ m2.setState( "l", "1", ABSENT );
+ m2.setState( "m", "1", PRESENT );
+ m2.setState( "n", "1", ABSENT );
+ m2.setState( "o", "1", ABSENT );
+ m2.setState( "p", "1", ABSENT );
+ m2.setState( "q", "1", ABSENT );
+ m2.setState( "r", "1", ABSENT );
+ m2.setState( "a", "2", ABSENT );
+ m2.setState( "b", "2", ABSENT );
+ m2.setState( "c", "2", ABSENT );
+ m2.setState( "d", "2", ABSENT );
+ m2.setState( "e", "2", ABSENT );
+ m2.setState( "f", "2", ABSENT );
+ m2.setState( "g", "2", ABSENT );
+ m2.setState( "h", "2", ABSENT );
+ m2.setState( "i", "2", ABSENT );
+ m2.setState( "j", "2", PRESENT );
+ m2.setState( "k", "2", ABSENT );
+ m2.setState( "l", "2", ABSENT );
+ m2.setState( "m", "2", PRESENT );
+ m2.setState( "n", "2", ABSENT );
+ m2.setState( "o", "2", ABSENT );
+ m2.setState( "p", "2", PRESENT );
+ m2.setState( "q", "2", ABSENT );
+ m2.setState( "r", "2", ABSENT );
+ m2.setState( "a", "3", ABSENT );
+ m2.setState( "b", "3", ABSENT );
+ m2.setState( "c", "3", PRESENT );
+ m2.setState( "d", "3", ABSENT );
+ m2.setState( "e", "3", ABSENT );
+ m2.setState( "f", "3", ABSENT );
+ m2.setState( "g", "3", PRESENT );
+ m2.setState( "h", "3", ABSENT );
+ m2.setState( "i", "3", ABSENT );
+ m2.setState( "j", "3", ABSENT );
+ m2.setState( "k", "3", ABSENT );
+ m2.setState( "l", "3", ABSENT );
+ m2.setState( "m", "3", ABSENT );
+ m2.setState( "n", "3", ABSENT );
+ m2.setState( "o", "3", ABSENT );
+ m2.setState( "p", "3", ABSENT );
+ m2.setState( "q", "3", ABSENT );
+ m2.setState( "r", "3", ABSENT );
+ dollo2.setReturnInternalStates( true );
+ dollo2.setReturnGainLossMatrix( true );
+ dollo2.execute( p2, m2 );
+ final CharacterStateMatrix<BinaryStates> i_m = dollo2.getInternalStatesMatrix();
+ final CharacterStateMatrix<GainLossStates> gl_m = dollo2.getGainLossMatrix();
+ if ( dollo2.getTotalGains() != 3 ) {
+ return false;
+ }
+ if ( dollo2.getTotalLosses() != 22 ) {
+ return false;
+ }
+ if ( dollo2.getTotalUnchanged() != 95 ) {
+ return false;
+ }
+ if ( i_m.getState( "ab", "0" ) != PRESENT ) {
+ return false;
+ }
+ if ( i_m.getState( "ac", "0" ) != PRESENT ) {
+ return false;
+ }
+ if ( i_m.getState( "ad", "0" ) != ABSENT ) {
+ return false;
+ }
+ if ( i_m.getState( "af", "0" ) != ABSENT ) {
+ return false;
+ }
+ if ( i_m.getState( "ef", "0" ) != ABSENT ) {
+ return false;
+ }
+ if ( i_m.getState( "ai", "0" ) != ABSENT ) {
+ return false;
+ }
+ if ( i_m.getState( "gi", "0" ) != ABSENT ) {
+ return false;
+ }
+ if ( i_m.getState( "jl", "0" ) != ABSENT ) {
+ return false;
+ }
+ if ( i_m.getState( "mo", "0" ) != ABSENT ) {
+ return false;
+ }
+ if ( i_m.getState( "pr", "0" ) != ABSENT ) {
+ return false;
+ }
+ if ( i_m.getState( "jr", "0" ) != ABSENT ) {
+ return false;
+ }
+ if ( i_m.getState( "root", "0" ) != ABSENT ) {
+ return false;
+ }
+ if ( i_m.getState( "ab", "1" ) != PRESENT ) {
+ return false;
+ }
+ if ( i_m.getState( "ac", "1" ) != PRESENT ) {
+ return false;
+ }
+ if ( i_m.getState( "ad", "1" ) != PRESENT ) {
+ return false;
+ }
+ if ( i_m.getState( "af", "1" ) != PRESENT ) {
+ return false;
+ }
+ if ( i_m.getState( "ef", "1" ) != ABSENT ) {
+ return false;
+ }
+ if ( i_m.getState( "ai", "1" ) != PRESENT ) {
+ return false;
+ }
+ if ( i_m.getState( "gi", "1" ) != PRESENT ) {
+ return false;
+ }
+ if ( i_m.getState( "jl", "1" ) != PRESENT ) {
+ return false;
+ }
+ if ( i_m.getState( "mo", "1" ) != PRESENT ) {
+ return false;
+ }
+ if ( i_m.getState( "pr", "1" ) != ABSENT ) {
+ return false;
+ }
+ if ( i_m.getState( "jr", "1" ) != PRESENT ) {
+ return false;
+ }
+ if ( i_m.getState( "root", "1" ) != PRESENT ) {
+ return false;
+ }
+ if ( i_m.getState( "ab", "2" ) != ABSENT ) {
+ return false;
+ }
+ if ( i_m.getState( "ac", "2" ) != ABSENT ) {
+ return false;
+ }
+ if ( i_m.getState( "ad", "2" ) != ABSENT ) {
+ return false;
+ }
+ if ( i_m.getState( "af", "2" ) != ABSENT ) {
+ return false;
+ }
+ if ( i_m.getState( "ef", "2" ) != ABSENT ) {
+ return false;
+ }
+ if ( i_m.getState( "ai", "2" ) != ABSENT ) {
+ return false;
+ }
+ if ( i_m.getState( "gi", "2" ) != ABSENT ) {
+ return false;
+ }
+ if ( i_m.getState( "jl", "2" ) != PRESENT ) {
+ return false;
+ }
+ if ( i_m.getState( "mo", "2" ) != PRESENT ) {
+ return false;
+ }
+ if ( i_m.getState( "pr", "2" ) != PRESENT ) {
+ return false;
+ }
+ if ( i_m.getState( "jr", "2" ) != PRESENT ) {
+ return false;
+ }
+ if ( i_m.getState( "root", "2" ) != ABSENT ) {
+ return false;
+ }
+ if ( i_m.getState( "ab", "3" ) != ABSENT ) {
+ return false;
+ }
+ if ( i_m.getState( "ac", "3" ) != PRESENT ) {
+ return false;
+ }
+ if ( i_m.getState( "ad", "3" ) != PRESENT ) {
+ return false;
+ }
+ if ( i_m.getState( "af", "3" ) != PRESENT ) {
+ return false;
+ }
+ if ( i_m.getState( "ef", "3" ) != ABSENT ) {
+ return false;
+ }
+ if ( i_m.getState( "ai", "3" ) != PRESENT ) {
+ return false;
+ }
+ if ( i_m.getState( "gi", "3" ) != PRESENT ) {
+ return false;
+ }
+ if ( i_m.getState( "jl", "3" ) != ABSENT ) {
+ return false;
+ }
+ if ( i_m.getState( "mo", "3" ) != ABSENT ) {
+ return false;
+ }
+ if ( i_m.getState( "pr", "3" ) != ABSENT ) {
+ return false;
+ }
+ if ( i_m.getState( "jr", "3" ) != ABSENT ) {
+ return false;
+ }
+ if ( i_m.getState( "root", "3" ) != ABSENT ) {
+ return false;
+ }
+ if ( gl_m.getState( "a", "0" ) != UNCHANGED_PRESENT ) {
+ return false;
+ }
+ final DolloParsimony dollo9 = DolloParsimony.createInstance();
+ final PhylogenyFactory factory9 = ParserBasedPhylogenyFactory.getInstance();
+ final String p9_str = "((((((a,b)ab,c)ac,d)ad,(e,f)ef)af,(g,h)gh)ah,i)r";
+ final Phylogeny p9 = factory9.create( p9_str, new NHXParser() )[ 0 ];
+ m1 = new BasicCharacterStateMatrix<CharacterStateMatrix.BinaryStates>( 9, 3 );
+ m1.setIdentifier( 0, "a" );
+ m1.setIdentifier( 1, "b" );
+ m1.setIdentifier( 2, "c" );
+ m1.setIdentifier( 3, "d" );
+ m1.setIdentifier( 4, "e" );
+ m1.setIdentifier( 5, "f" );
+ m1.setIdentifier( 6, "g" );
+ m1.setIdentifier( 7, "h" );
+ m1.setIdentifier( 8, "i" );
+ m1.setState( 0, 0, PRESENT );
+ m1.setState( 1, 0, ABSENT );
+ m1.setState( 2, 0, PRESENT );
+ m1.setState( 3, 0, ABSENT );
+ m1.setState( 4, 0, ABSENT );
+ m1.setState( 5, 0, ABSENT );
+ m1.setState( 6, 0, ABSENT );
+ m1.setState( 7, 0, ABSENT );
+ m1.setState( 8, 0, ABSENT );
+ m1.setState( 0, 1, PRESENT );
+ m1.setState( 1, 1, PRESENT );
+ m1.setState( 2, 1, PRESENT );
+ m1.setState( 3, 1, PRESENT );
+ m1.setState( 4, 1, ABSENT );
+ m1.setState( 5, 1, ABSENT );
+ m1.setState( 6, 1, ABSENT );
+ m1.setState( 7, 1, ABSENT );
+ m1.setState( 8, 1, ABSENT );
+ m1.setState( 0, 2, PRESENT );
+ m1.setState( 1, 2, ABSENT );
+ m1.setState( 2, 2, ABSENT );
+ m1.setState( 3, 2, ABSENT );
+ m1.setState( 4, 2, ABSENT );
+ m1.setState( 5, 2, ABSENT );
+ m1.setState( 6, 2, ABSENT );
+ m1.setState( 7, 2, PRESENT );
+ m1.setState( 8, 2, ABSENT );
+ dollo9.execute( p9, m1 );
+ if ( dollo9.getTotalGains() != 3 ) {
+ return false;
+ }
+ if ( dollo9.getTotalLosses() != 6 ) {
+ return false;
+ }
+ final DolloParsimony dollo10 = DolloParsimony.createInstance();
+ final PhylogenyFactory factory10 = ParserBasedPhylogenyFactory.getInstance();
+ final String p10_str = "((((((a,b)ab,c)ac,d)ad,(e,f)ef)af,(g,h)gh)ah,i)r";
+ final Phylogeny p10 = factory10.create( p10_str, new NHXParser() )[ 0 ];
+ final CharacterStateMatrix<CharacterStateMatrix.BinaryStates> m10 = new BasicCharacterStateMatrix<CharacterStateMatrix.BinaryStates>( 9,
+ 1 );
+ m10.setIdentifier( 0, "a" );
+ m10.setIdentifier( 1, "b" );
+ m10.setIdentifier( 2, "c" );
+ m10.setIdentifier( 3, "d" );
+ m10.setIdentifier( 4, "e" );
+ m10.setIdentifier( 5, "f" );
+ m10.setIdentifier( 6, "g" );
+ m10.setIdentifier( 7, "h" );
+ m10.setIdentifier( 8, "i" );
+ m10.setState( 0, 0, PRESENT );
+ m10.setState( 1, 0, ABSENT );
+ m10.setState( 2, 0, PRESENT );
+ m10.setState( 3, 0, ABSENT );
+ m10.setState( 4, 0, ABSENT );
+ m10.setState( 5, 0, ABSENT );
+ m10.setState( 6, 0, ABSENT );
+ m10.setState( 7, 0, ABSENT );
+ m10.setState( 8, 0, ABSENT );
+ dollo10.execute( p10, m10 );
+ if ( dollo10.getTotalGains() != 1 ) {
+ return false;
+ }
+ if ( dollo10.getTotalLosses() != 1 ) {
+ return false;
+ }
+ }
+ catch ( final Exception e ) {
+ e.printStackTrace( System.out );
+ return false;
+ }
+ return true;
+ }
+
+ private static boolean testDolloParsimonyOnNonBinaryTree() {
+ try {
+ final BinaryStates PRESENT = BinaryStates.PRESENT;
+ final BinaryStates ABSENT = BinaryStates.ABSENT;
+ final DolloParsimony dollo1 = DolloParsimony.createInstance();
+ final PhylogenyFactory factory1 = ParserBasedPhylogenyFactory.getInstance();
+ final String p1_str = "((((((a,b,y)aby,c)ac,d)ad,(e,f)ef)af,(g,h)gh)ah,i)r";
+ final Phylogeny p1 = factory1.create( p1_str, new NHXParser() )[ 0 ];
+ final CharacterStateMatrix<CharacterStateMatrix.BinaryStates> m1 = new BasicCharacterStateMatrix<CharacterStateMatrix.BinaryStates>( 10,
+ 1 );
+ m1.setIdentifier( 0, "a" );
+ m1.setIdentifier( 1, "b" );
+ m1.setIdentifier( 2, "y" );
+ m1.setIdentifier( 3, "c" );
+ m1.setIdentifier( 4, "d" );
+ m1.setIdentifier( 5, "e" );
+ m1.setIdentifier( 6, "f" );
+ m1.setIdentifier( 7, "g" );
+ m1.setIdentifier( 8, "h" );
+ m1.setIdentifier( 9, "i" );
+ m1.setCharacter( 0, "0" );
+ m1.setState( "a", "0", PRESENT );
+ m1.setState( "b", "0", ABSENT );
+ m1.setState( "y", "0", PRESENT );
+ m1.setState( "c", "0", PRESENT );
+ m1.setState( "d", "0", ABSENT );
+ m1.setState( "e", "0", ABSENT );
+ m1.setState( "f", "0", ABSENT );
+ m1.setState( "g", "0", ABSENT );
+ m1.setState( "h", "0", ABSENT );
+ m1.setState( "i", "0", ABSENT );
+ dollo1.execute( p1, m1 );
+ if ( dollo1.getTotalGains() != 1 ) {
+ return false;
+ }
+ if ( dollo1.getTotalLosses() != 1 ) {
+ return false;
+ }
+ if ( dollo1.getTotalUnchanged() != 16 ) {
+ return false;
+ }
+ m1.setState( "b", "0", PRESENT );
+ dollo1.execute( p1, m1 );
+ if ( dollo1.getTotalGains() != 1 ) {
+ return false;
+ }
+ if ( dollo1.getTotalLosses() != 0 ) {
+ return false;
+ }
+ if ( dollo1.getTotalUnchanged() != 17 ) {
+ return false;
+ }
+ m1.setState( "a", "0", ABSENT );
+ m1.setState( "b", "0", ABSENT );
+ dollo1.execute( p1, m1 );
+ if ( dollo1.getTotalGains() != 1 ) {
+ return false;
+ }
+ if ( dollo1.getTotalLosses() != 2 ) {
+ return false;
+ }
+ if ( dollo1.getTotalUnchanged() != 15 ) {
+ return false;
+ }
+ m1.setState( "y", "0", ABSENT );
+ dollo1.execute( p1, m1 );
+ if ( dollo1.getTotalGains() != 1 ) {
+ return false;
+ }
+ if ( dollo1.getTotalLosses() != 0 ) {
+ return false;
+ }
+ if ( dollo1.getTotalUnchanged() != 17 ) {
+ return false;
+ }
+ final DolloParsimony dollo2 = DolloParsimony.createInstance();
+ final PhylogenyFactory factory2 = ParserBasedPhylogenyFactory.getInstance();
+ final String p2_str = "((((((a,b,y)aby,c,d)cad,e,f)af,(g,h)gh)ah,i))r";
+ final Phylogeny p2 = factory2.create( p2_str, new NHXParser() )[ 0 ];
+ final CharacterStateMatrix<CharacterStateMatrix.BinaryStates> m2 = new BasicCharacterStateMatrix<CharacterStateMatrix.BinaryStates>( 10,
+ 1 );
+ m2.setIdentifier( 0, "a" );
+ m2.setIdentifier( 1, "b" );
+ m2.setIdentifier( 2, "y" );
+ m2.setIdentifier( 3, "c" );
+ m2.setIdentifier( 4, "d" );
+ m2.setIdentifier( 5, "e" );
+ m2.setIdentifier( 6, "f" );
+ m2.setIdentifier( 7, "g" );
+ m2.setIdentifier( 8, "h" );
+ m2.setIdentifier( 9, "i" );
+ m2.setCharacter( 0, "0" );
+ m2.setState( "a", "0", PRESENT );
+ m2.setState( "b", "0", ABSENT );
+ m2.setState( "y", "0", PRESENT );
+ m2.setState( "c", "0", PRESENT );
+ m2.setState( "d", "0", ABSENT );
+ m2.setState( "e", "0", ABSENT );
+ m2.setState( "f", "0", ABSENT );
+ m2.setState( "g", "0", ABSENT );
+ m2.setState( "h", "0", ABSENT );
+ m2.setState( "i", "0", ABSENT );
+ dollo2.setReturnInternalStates( true );
+ dollo2.execute( p2, m2 );
+ CharacterStateMatrix<BinaryStates> i_m2 = dollo2.getInternalStatesMatrix();
+ if ( i_m2.getState( "aby", "0" ) != PRESENT ) {
+ return false;
+ }
+ if ( i_m2.getState( "cad", "0" ) != PRESENT ) {
+ return false;
+ }
+ if ( i_m2.getState( "af", "0" ) != ABSENT ) {
+ return false;
+ }
+ if ( i_m2.getState( "gh", "0" ) != ABSENT ) {
+ return false;
+ }
+ if ( i_m2.getState( "ah", "0" ) != ABSENT ) {
+ return false;
+ }
+ if ( i_m2.getState( "r", "0" ) != ABSENT ) {
+ return false;
+ }
+ if ( dollo2.getTotalGains() != 1 ) {
+ return false;
+ }
+ if ( dollo2.getTotalLosses() != 2 ) {
+ return false;
+ }
+ if ( dollo2.getTotalUnchanged() != 14 ) {
+ return false;
+ }
+ m2.setState( "b", "0", PRESENT );
+ dollo2.execute( p2, m2 );
+ if ( dollo2.getTotalGains() != 1 ) {
+ return false;
+ }
+ if ( dollo2.getTotalLosses() != 1 ) {
+ return false;
+ }
+ if ( dollo2.getTotalUnchanged() != 15 ) {
+ return false;
+ }
+ m2.setState( "a", "0", ABSENT );
+ m2.setState( "b", "0", ABSENT );
+ dollo2.execute( p2, m2 );
+ if ( dollo2.getTotalGains() != 1 ) {
+ return false;
+ }
+ if ( dollo2.getTotalLosses() != 3 ) {
+ return false;
+ }
+ if ( dollo2.getTotalUnchanged() != 13 ) {
+ return false;
+ }
+ m2.setState( "y", "0", ABSENT );
+ dollo2.execute( p2, m2 );
+ if ( dollo2.getTotalGains() != 1 ) {
+ return false;
+ }
+ if ( dollo2.getTotalLosses() != 0 ) {
+ return false;
+ }
+ if ( dollo2.getTotalUnchanged() != 16 ) {
+ return false;
+ }
+ m2.setState( "c", "0", ABSENT );
+ dollo2.execute( p2, m2 );
+ if ( dollo2.getTotalGains() != 0 ) {
+ return false;
+ }
+ if ( dollo2.getTotalLosses() != 0 ) {
+ return false;
+ }
+ if ( dollo2.getTotalUnchanged() != 17 ) {
+ return false;
+ }
+ m2.setState( "y", "0", PRESENT );
+ m2.setState( "e", "0", PRESENT );
+ dollo2.execute( p2, m2 );
+ if ( dollo2.getTotalGains() != 1 ) {
+ return false;
+ }
+ if ( dollo2.getTotalLosses() != 5 ) {
+ return false;
+ }
+ if ( dollo2.getTotalUnchanged() != 11 ) {
+ return false;
+ }
+ i_m2 = dollo2.getInternalStatesMatrix();
+ if ( i_m2.getState( "aby", "0" ) != PRESENT ) {
+ return false;
+ }
+ if ( i_m2.getState( "cad", "0" ) != PRESENT ) {
+ return false;
+ }
+ if ( i_m2.getState( "af", "0" ) != PRESENT ) {
+ return false;
+ }
+ if ( i_m2.getState( "gh", "0" ) != ABSENT ) {
+ return false;
+ }
+ if ( i_m2.getState( "ah", "0" ) != ABSENT ) {
+ return false;
+ }
+ if ( i_m2.getState( "r", "0" ) != ABSENT ) {
+ return false;
+ }
+ }
+ catch ( final Exception e ) {
+ e.printStackTrace( System.out );
+ return false;
+ }
+ return true;
+ }
+
+ private static boolean testFitchParsimony() {
+ try {
+ final BinaryStates PRESENT = BinaryStates.PRESENT;
+ final BinaryStates ABSENT = BinaryStates.ABSENT;
+ final GainLossStates GAIN = GainLossStates.GAIN;
+ final GainLossStates LOSS = GainLossStates.LOSS;
+ final GainLossStates UNCHANGED_PRESENT = GainLossStates.UNCHANGED_PRESENT;
+ final GainLossStates UNCHANGED_ABSENT = GainLossStates.UNCHANGED_ABSENT;
+ final FitchParsimony<String> fitch1 = new FitchParsimony<String>();
+ final PhylogenyFactory factory1 = ParserBasedPhylogenyFactory.getInstance();
+ final String p1_str = "((((((a,b)ab,c)ac,d)ad,(e,f)ef)af,(g,h,i)gi)ai,((j,k,l)jl,(m,n,o)mo,(p,q,r)pr)jr)root";
+ final Phylogeny p1 = factory1.create( p1_str, new NHXParser() )[ 0 ];
+ final CharacterStateMatrix<String> m1 = new BasicCharacterStateMatrix<String>( 18, 1 );
+ m1.setIdentifier( 0, "a" );
+ m1.setIdentifier( 1, "b" );
+ m1.setIdentifier( 2, "c" );
+ m1.setIdentifier( 3, "d" );
+ m1.setIdentifier( 4, "e" );
+ m1.setIdentifier( 5, "f" );
+ m1.setIdentifier( 6, "g" );
+ m1.setIdentifier( 7, "h" );
+ m1.setIdentifier( 8, "i" );
+ m1.setIdentifier( 9, "j" );
+ m1.setIdentifier( 10, "k" );
+ m1.setIdentifier( 11, "l" );
+ m1.setIdentifier( 12, "m" );
+ m1.setIdentifier( 13, "n" );
+ m1.setIdentifier( 14, "o" );
+ m1.setIdentifier( 15, "p" );
+ m1.setIdentifier( 16, "q" );
+ m1.setIdentifier( 17, "r" );
+ m1.setCharacter( 0, "0" );
+ m1.setState( "a", "0", "A" );
+ m1.setState( "b", "0", "A" );
+ m1.setState( "c", "0", "B" );
+ m1.setState( "d", "0", "C" );
+ m1.setState( "e", "0", "D" );
+ m1.setState( "f", "0", "A" );
+ m1.setState( "g", "0", "A" );
+ m1.setState( "h", "0", "B" );
+ m1.setState( "i", "0", "C" );
+ m1.setState( "j", "0", "A" );
+ m1.setState( "k", "0", "B" );
+ m1.setState( "l", "0", "C" );
+ m1.setState( "m", "0", "B" );
+ m1.setState( "n", "0", "B" );
+ m1.setState( "o", "0", "B" );
+ m1.setState( "p", "0", "A" );
+ m1.setState( "q", "0", "C" );
+ m1.setState( "r", "0", "D" );
+ fitch1.setReturnInternalStates( true );
+ fitch1.setReturnGainLossMatrix( false );
+ fitch1.setRandomize( false );
+ fitch1.execute( p1, m1 );
+ final CharacterStateMatrix<String> i_m = fitch1.getInternalStatesMatrix();
+ final CharacterStateMatrix<List<String>> i_m_all = fitch1.getInternalStatesMatrixPriorToTraceback();
+ if ( fitch1.getCost() != 10 ) {
+ return false;
+ }
+ if ( !i_m.getState( "ab", "0" ).equals( "A" ) ) {
+ return false;
+ }
+ if ( !i_m.getState( "ac", "0" ).equals( "A" ) ) {
+ return false;
+ }
+ if ( !i_m.getState( "ad", "0" ).equals( "A" ) ) {
+ return false;
+ }
+ if ( !i_m.getState( "ef", "0" ).equals( "A" ) ) {
+ return false;
+ }
+ if ( !i_m.getState( "ai", "0" ).equals( "A" ) ) {
+ return false;
+ }
+ if ( !i_m.getState( "gi", "0" ).equals( "A" ) ) {
+ return false;
+ }
+ if ( !i_m.getState( "jl", "0" ).equals( "A" ) ) {
+ return false;
+ }
+ if ( !i_m.getState( "mo", "0" ).equals( "B" ) ) {
+ return false;
+ }
+ if ( !i_m.getState( "pr", "0" ).equals( "A" ) ) {
+ return false;
+ }
+ if ( i_m_all.getState( "ab", "0" ).size() != 1 ) {
+ return false;
+ }
+ if ( !i_m_all.getState( "ab", "0" ).contains( "A" ) ) {
+ return false;
+ }
+ if ( i_m_all.getState( "ac", "0" ).size() != 2 ) {
+ return false;
+ }
+ if ( !i_m_all.getState( "ac", "0" ).contains( "A" ) ) {
+ return false;
+ }
+ if ( !i_m_all.getState( "ac", "0" ).contains( "B" ) ) {
+ return false;
+ }
+ if ( i_m_all.getState( "ad", "0" ).size() != 3 ) {
+ return false;
+ }
+ if ( !i_m_all.getState( "ad", "0" ).contains( "A" ) ) {
+ return false;
+ }
+ if ( !i_m_all.getState( "ad", "0" ).contains( "B" ) ) {
+ return false;
+ }
+ if ( !i_m_all.getState( "ad", "0" ).contains( "C" ) ) {
+ return false;
+ }
+ if ( i_m_all.getState( "af", "0" ).size() != 1 ) {
+ return false;
+ }
+ if ( !i_m_all.getState( "af", "0" ).contains( "A" ) ) {
+ return false;
+ }
+ if ( i_m_all.getState( "ef", "0" ).size() != 2 ) {
+ return false;
+ }
+ if ( !i_m_all.getState( "ef", "0" ).contains( "A" ) ) {
+ return false;
+ }
+ if ( !i_m_all.getState( "ef", "0" ).contains( "D" ) ) {
+ return false;
+ }
+ if ( i_m_all.getState( "gi", "0" ).size() != 3 ) {
+ return false;
+ }
+ if ( !i_m_all.getState( "gi", "0" ).contains( "A" ) ) {
+ return false;
+ }
+ if ( !i_m_all.getState( "gi", "0" ).contains( "B" ) ) {
+ return false;
+ }
+ if ( !i_m_all.getState( "gi", "0" ).contains( "C" ) ) {
+ return false;
+ }
+ if ( i_m_all.getState( "ai", "0" ).size() != 1 ) {
+ return false;
+ }
+ if ( !i_m_all.getState( "ai", "0" ).contains( "A" ) ) {
+ return false;
+ }
+ if ( i_m_all.getState( "jl", "0" ).size() != 3 ) {
+ return false;
+ }
+ if ( !i_m_all.getState( "jl", "0" ).contains( "A" ) ) {
+ return false;
+ }
+ if ( !i_m_all.getState( "jl", "0" ).contains( "B" ) ) {
+ return false;
+ }
+ if ( !i_m_all.getState( "jl", "0" ).contains( "C" ) ) {
+ return false;
+ }
+ if ( i_m_all.getState( "mo", "0" ).size() != 1 ) {
+ return false;
+ }
+ if ( !i_m_all.getState( "mo", "0" ).contains( "B" ) ) {
+ return false;
+ }
+ if ( i_m_all.getState( "pr", "0" ).size() != 3 ) {
+ return false;
+ }
+ if ( !i_m_all.getState( "pr", "0" ).contains( "A" ) ) {
+ return false;
+ }
+ if ( !i_m_all.getState( "pr", "0" ).contains( "C" ) ) {
+ return false;
+ }
+ if ( !i_m_all.getState( "pr", "0" ).contains( "D" ) ) {
+ return false;
+ }
+ if ( i_m_all.getState( "jr", "0" ).size() != 4 ) {
+ return false;
+ }
+ if ( !i_m_all.getState( "jr", "0" ).contains( "A" ) ) {
+ return false;
+ }
+ if ( !i_m_all.getState( "jr", "0" ).contains( "B" ) ) {
+ return false;
+ }
+ if ( !i_m_all.getState( "jr", "0" ).contains( "C" ) ) {
+ return false;
+ }
+ if ( !i_m_all.getState( "jr", "0" ).contains( "D" ) ) {
+ return false;
+ }
+ final FitchParsimony<String> fitch2 = new FitchParsimony<String>();
+ final PhylogenyFactory factory2 = ParserBasedPhylogenyFactory.getInstance();
+ final String p2_str = "((a,b)ab,(c,(d,e)de)cde)r";
+ final Phylogeny p2 = factory2.create( p2_str, new NHXParser() )[ 0 ];
+ final CharacterStateMatrix<String> m2 = new BasicCharacterStateMatrix<String>( 5, 1 );
+ m2.setIdentifier( 0, "a" );
+ m2.setIdentifier( 1, "b" );
+ m2.setIdentifier( 2, "c" );
+ m2.setIdentifier( 3, "d" );
+ m2.setIdentifier( 4, "e" );
+ m2.setCharacter( 0, "0" );
+ m2.setState( "a", "0", "C" );
+ m2.setState( "b", "0", "A" );
+ m2.setState( "c", "0", "C" );
+ m2.setState( "d", "0", "A" );
+ m2.setState( "e", "0", "G" );
+ fitch2.setReturnInternalStates( true );
+ fitch2.setReturnGainLossMatrix( false );
+ fitch2.execute( p2, m2 );
+ final CharacterStateMatrix<String> i_m2 = fitch2.getInternalStatesMatrix();
+ final CharacterStateMatrix<List<String>> i_m_all2 = fitch2.getInternalStatesMatrixPriorToTraceback();
+ if ( fitch2.getCost() != 3 ) {
+ return false;
+ }
+ if ( !i_m2.getState( "ab", "0" ).equals( "A" ) ) {
+ return false;
+ }
+ if ( !i_m2.getState( "de", "0" ).equals( "A" ) ) {
+ return false;
+ }
+ if ( !i_m2.getState( "cde", "0" ).equals( "A" ) ) {
+ return false;
+ }
+ if ( !i_m2.getState( "r", "0" ).equals( "A" ) ) {
+ return false;
+ }
+ if ( i_m_all2.getState( "cde", "0" ).size() != 3 ) {
+ return false;
+ }
+ if ( !i_m_all2.getState( "cde", "0" ).contains( "A" ) ) {
+ return false;
+ }
+ if ( !i_m_all2.getState( "cde", "0" ).contains( "C" ) ) {
+ return false;
+ }
+ if ( !i_m_all2.getState( "cde", "0" ).contains( "G" ) ) {
+ return false;
+ }
+ if ( i_m_all2.getState( "ab", "0" ).size() != 2 ) {
+ return false;
+ }
+ if ( !i_m_all2.getState( "ab", "0" ).contains( "A" ) ) {
+ return false;
+ }
+ if ( !i_m_all2.getState( "ab", "0" ).contains( "C" ) ) {
+ return false;
+ }
+ fitch2.setReturnInternalStates( true );
+ fitch2.setReturnGainLossMatrix( false );
+ fitch2.setUseLast( true );
+ fitch2.execute( p2, m2 );
+ final CharacterStateMatrix<String> i_m21 = fitch2.getInternalStatesMatrix();
+ final CharacterStateMatrix<List<String>> i_m_all21 = fitch2.getInternalStatesMatrixPriorToTraceback();
+ if ( fitch2.getCost() != 3 ) {
+ return false;
+ }
+ if ( !i_m21.getState( "ab", "0" ).equals( "C" ) ) {
+ return false;
+ }
+ if ( !i_m21.getState( "de", "0" ).equals( "G" ) ) {
+ return false;
+ }
+ if ( !i_m21.getState( "cde", "0" ).equals( "C" ) ) {
+ return false;
+ }
+ if ( !i_m21.getState( "r", "0" ).equals( "C" ) ) {
+ return false;
+ }
+ if ( i_m_all21.getState( "cde", "0" ).size() != 3 ) {
+ return false;
+ }
+ if ( !i_m_all21.getState( "cde", "0" ).contains( "A" ) ) {
+ return false;
+ }
+ if ( !i_m_all21.getState( "cde", "0" ).contains( "C" ) ) {
+ return false;
+ }
+ if ( !i_m_all21.getState( "cde", "0" ).contains( "G" ) ) {
+ return false;
+ }
+ final FitchParsimony<String> fitch3 = new FitchParsimony<String>();
+ final PhylogenyFactory factory3 = ParserBasedPhylogenyFactory.getInstance();
+ final String p3_str = "(((a,b)ab,((c,d)cd,e)cde)abcde,f)r";
+ final Phylogeny p3 = factory3.create( p3_str, new NHXParser() )[ 0 ];
+ final CharacterStateMatrix<String> m3 = new BasicCharacterStateMatrix<String>( 6, 1 );
+ m3.setIdentifier( 0, "a" );
+ m3.setIdentifier( 1, "b" );
+ m3.setIdentifier( 2, "c" );
+ m3.setIdentifier( 3, "d" );
+ m3.setIdentifier( 4, "e" );
+ m3.setIdentifier( 5, "f" );
+ m3.setCharacter( 0, "0" );
+ m3.setState( "a", "0", "C" );
+ m3.setState( "b", "0", "U" );
+ m3.setState( "c", "0", "G" );
+ m3.setState( "d", "0", "U" );
+ m3.setState( "e", "0", "A" );
+ m3.setState( "f", "0", "A" );
+ fitch3.setReturnInternalStates( true );
+ fitch3.setReturnGainLossMatrix( false );
+ fitch3.execute( p3, m3 );
+ final CharacterStateMatrix<String> i_m3 = fitch3.getInternalStatesMatrix();
+ final CharacterStateMatrix<List<String>> i_m_all3 = fitch3.getInternalStatesMatrixPriorToTraceback();
+ if ( fitch3.getCost() != 4 ) {
+ return false;
+ }
+ if ( !i_m3.getState( "ab", "0" ).equals( "U" ) ) {
+ return false;
+ }
+ if ( !i_m3.getState( "cd", "0" ).equals( "U" ) ) {
+ return false;
+ }
+ if ( !i_m3.getState( "cde", "0" ).equals( "U" ) ) {
+ return false;
+ }
+ if ( !i_m3.getState( "abcde", "0" ).equals( "U" ) ) {
+ return false;
+ }
+ if ( !i_m3.getState( "r", "0" ).equals( "A" ) ) {
+ return false;
+ }
+ if ( i_m_all3.getState( "cde", "0" ).size() != 3 ) {
+ return false;
+ }
+ if ( !i_m_all3.getState( "cde", "0" ).contains( "A" ) ) {
+ return false;
+ }
+ if ( !i_m_all3.getState( "cde", "0" ).contains( "G" ) ) {
+ return false;
+ }
+ if ( !i_m_all3.getState( "cde", "0" ).contains( "U" ) ) {
+ return false;
+ }
+ if ( i_m_all3.getState( "ab", "0" ).size() != 2 ) {
+ return false;
+ }
+ if ( !i_m_all3.getState( "ab", "0" ).contains( "C" ) ) {
+ return false;
+ }
+ if ( !i_m_all3.getState( "ab", "0" ).contains( "U" ) ) {
+ return false;
+ }
+ if ( i_m_all3.getState( "cd", "0" ).size() != 2 ) {
+ return false;
+ }
+ if ( !i_m_all3.getState( "cd", "0" ).contains( "G" ) ) {
+ return false;
+ }
+ if ( !i_m_all3.getState( "cd", "0" ).contains( "U" ) ) {
+ return false;
+ }
+ if ( i_m_all3.getState( "abcde", "0" ).size() != 1 ) {
+ return false;
+ }
+ if ( !i_m_all3.getState( "abcde", "0" ).contains( "U" ) ) {
+ return false;
+ }
+ if ( i_m_all3.getState( "r", "0" ).size() != 2 ) {
+ return false;
+ }
+ if ( !i_m_all3.getState( "r", "0" ).contains( "A" ) ) {
+ return false;
+ }
+ if ( !i_m_all3.getState( "r", "0" ).contains( "U" ) ) {
+ return false;
+ }
+ final FitchParsimony<BinaryStates> fitch4 = new FitchParsimony<BinaryStates>();
+ final PhylogenyFactory factory4 = ParserBasedPhylogenyFactory.getInstance();
+ final String p4_str = "(((a,b)ab,((c,d)cd,e)cde)abcde,f)r";
+ final Phylogeny p4 = factory4.create( p4_str, new NHXParser() )[ 0 ];
+ final CharacterStateMatrix<BinaryStates> m4 = new BasicCharacterStateMatrix<BinaryStates>( 6, 1 );
+ m4.setIdentifier( 0, "a" );
+ m4.setIdentifier( 1, "b" );
+ m4.setIdentifier( 2, "c" );
+ m4.setIdentifier( 3, "d" );
+ m4.setIdentifier( 4, "e" );
+ m4.setIdentifier( 5, "f" );
+ m4.setCharacter( 0, "0" );
+ m4.setState( "a", "0", PRESENT );
+ m4.setState( "b", "0", ABSENT );
+ m4.setState( "c", "0", PRESENT );
+ m4.setState( "d", "0", PRESENT );
+ m4.setState( "e", "0", ABSENT );
+ m4.setState( "f", "0", ABSENT );
+ fitch4.setReturnInternalStates( true );
+ fitch4.setReturnGainLossMatrix( true );
+ fitch4.execute( p4, m4 );
+ final CharacterStateMatrix<GainLossStates> gl_m_4 = fitch4.getGainLossMatrix();
+ if ( fitch4.getCost() != 2 ) {
+ return false;
+ }
+ if ( fitch4.getTotalLosses() != 0 ) {
+ return false;
+ }
+ if ( fitch4.getTotalGains() != 2 ) {
+ return false;
+ }
+ if ( fitch4.getTotalUnchanged() != 9 ) {
+ return false;
+ }
+ if ( gl_m_4.getState( "a", "0" ) != GAIN ) {
+ return false;
+ }
+ if ( gl_m_4.getState( "b", "0" ) != UNCHANGED_ABSENT ) {
+ return false;
+ }
+ if ( gl_m_4.getState( "ab", "0" ) != UNCHANGED_ABSENT ) {
+ return false;
+ }
+ if ( gl_m_4.getState( "cd", "0" ) != GAIN ) {
+ return false;
+ }
+ if ( gl_m_4.getState( "r", "0" ) != UNCHANGED_ABSENT ) {
+ return false;
+ }
+ final FitchParsimony<BinaryStates> fitch5 = new FitchParsimony<BinaryStates>();
+ final PhylogenyFactory factory5 = ParserBasedPhylogenyFactory.getInstance();
+ final String p5_str = "(((a,b)ab,((c,d)cd,e)cde)abcde,f)r";
+ final Phylogeny p5 = factory5.create( p5_str, new NHXParser() )[ 0 ];
+ final CharacterStateMatrix<BinaryStates> m5 = new BasicCharacterStateMatrix<BinaryStates>( 6, 1 );
+ m5.setIdentifier( 0, "a" );
+ m5.setIdentifier( 1, "b" );
+ m5.setIdentifier( 2, "c" );
+ m5.setIdentifier( 3, "d" );
+ m5.setIdentifier( 4, "e" );
+ m5.setIdentifier( 5, "f" );
+ m5.setCharacter( 0, "0" );
+ m5.setState( "a", "0", PRESENT );
+ m5.setState( "b", "0", ABSENT );
+ m5.setState( "c", "0", PRESENT );
+ m5.setState( "d", "0", ABSENT );
+ m5.setState( "e", "0", PRESENT );
+ m5.setState( "f", "0", ABSENT );
+ fitch5.setReturnInternalStates( true );
+ fitch5.setReturnGainLossMatrix( true );
+ fitch5.execute( p5, m5 );
+ final CharacterStateMatrix<GainLossStates> gl_m_5 = fitch5.getGainLossMatrix();
+ if ( fitch5.getCost() != 3 ) {
+ return false;
+ }
+ if ( fitch5.getTotalLosses() != 2 ) {
+ return false;
+ }
+ if ( fitch5.getTotalGains() != 1 ) {
+ return false;
+ }
+ if ( fitch5.getTotalUnchanged() != 8 ) {
+ return false;
+ }
+ if ( gl_m_5.getState( "abcde", "0" ) != GAIN ) {
+ return false;
+ }
+ if ( gl_m_5.getState( "a", "0" ) != UNCHANGED_PRESENT ) {
+ return false;
+ }
+ if ( gl_m_5.getState( "b", "0" ) != LOSS ) {
+ return false;
+ }
+ if ( gl_m_5.getState( "d", "0" ) != LOSS ) {
+ return false;
+ }
+ if ( gl_m_5.getState( "r", "0" ) != UNCHANGED_ABSENT ) {
+ return false;
+ }
+ final FitchParsimony<BinaryStates> fitch6 = new FitchParsimony<BinaryStates>();
+ final PhylogenyFactory factory6 = ParserBasedPhylogenyFactory.getInstance();
+ final String p6_str = "(((a,b)ab,((c,d)cd,e)cde)abcde,f)r";
+ final Phylogeny p6 = factory6.create( p6_str, new NHXParser() )[ 0 ];
+ final CharacterStateMatrix<BinaryStates> m6 = new BasicCharacterStateMatrix<BinaryStates>( 6, 1 );
+ m6.setIdentifier( 0, "a" );
+ m6.setIdentifier( 1, "b" );
+ m6.setIdentifier( 2, "c" );
+ m6.setIdentifier( 3, "d" );
+ m6.setIdentifier( 4, "e" );
+ m6.setIdentifier( 5, "f" );
+ m6.setCharacter( 0, "0" );
+ m6.setState( "a", "0", PRESENT );
+ m6.setState( "b", "0", ABSENT );
+ m6.setState( "c", "0", PRESENT );
+ m6.setState( "d", "0", PRESENT );
+ m6.setState( "e", "0", ABSENT );
+ m6.setState( "f", "0", PRESENT );
+ fitch6.setReturnInternalStates( true );
+ fitch6.setReturnGainLossMatrix( true );
+ fitch6.execute( p6, m6 );
+ final CharacterStateMatrix<GainLossStates> gl_m_6 = fitch6.getGainLossMatrix();
+ if ( fitch6.getCost() != 2 ) {
+ return false;
+ }
+ if ( fitch6.getTotalLosses() != 2 ) {
+ return false;
+ }
+ if ( fitch6.getTotalGains() != 0 ) {
+ return false;
+ }
+ if ( fitch6.getTotalUnchanged() != 9 ) {
+ return false;
+ }
+ if ( gl_m_6.getState( "abcde", "0" ) != UNCHANGED_PRESENT ) {
+ return false;
+ }
+ if ( gl_m_6.getState( "r", "0" ) != UNCHANGED_PRESENT ) {
+ return false;
+ }
+ if ( gl_m_6.getState( "b", "0" ) != LOSS ) {
+ return false;
+ }
+ if ( gl_m_6.getState( "e", "0" ) != LOSS ) {
+ return false;
+ }
+ final FitchParsimony<BinaryStates> fitch7 = new FitchParsimony<BinaryStates>();
+ final PhylogenyFactory factory7 = ParserBasedPhylogenyFactory.getInstance();
+ final String p7_str = "(((a,b)ab,(c,d)cd)abcd,((e,f)ef,(g,h)gh)efgh)r";
+ final Phylogeny p7 = factory7.create( p7_str, new NHXParser() )[ 0 ];
+ final CharacterStateMatrix<BinaryStates> m7 = new BasicCharacterStateMatrix<BinaryStates>( 8, 1 );
+ m7.setIdentifier( 0, "a" );
+ m7.setIdentifier( 1, "b" );
+ m7.setIdentifier( 2, "c" );
+ m7.setIdentifier( 3, "d" );
+ m7.setIdentifier( 4, "e" );
+ m7.setIdentifier( 5, "f" );
+ m7.setIdentifier( 6, "g" );
+ m7.setIdentifier( 7, "h" );
+ m7.setCharacter( 0, "0" );
+ m7.setState( "a", "0", PRESENT );
+ m7.setState( "b", "0", ABSENT );
+ m7.setState( "c", "0", PRESENT );
+ m7.setState( "d", "0", ABSENT );
+ m7.setState( "e", "0", PRESENT );
+ m7.setState( "f", "0", ABSENT );
+ m7.setState( "g", "0", PRESENT );
+ m7.setState( "h", "0", ABSENT );
+ fitch7.setReturnInternalStates( true );
+ fitch7.setReturnGainLossMatrix( true );
+ fitch7.execute( p7, m7 );
+ final CharacterStateMatrix<GainLossStates> gl_m_7 = fitch7.getGainLossMatrix();
+ if ( fitch7.getCost() != 4 ) {
+ return false;
+ }
+ if ( fitch7.getTotalLosses() != 0 ) {
+ return false;
+ }
+ if ( fitch7.getTotalGains() != 4 ) {
+ return false;
+ }
+ if ( fitch7.getTotalUnchanged() != 11 ) {
+ return false;
+ }
+ if ( gl_m_7.getState( "a", "0" ) != GAIN ) {
+ return false;
+ }
+ if ( gl_m_7.getState( "c", "0" ) != GAIN ) {
+ return false;
+ }
+ if ( gl_m_7.getState( "e", "0" ) != GAIN ) {
+ return false;
+ }
+ if ( gl_m_7.getState( "g", "0" ) != GAIN ) {
+ return false;
+ }
+ if ( gl_m_7.getState( "r", "0" ) != UNCHANGED_ABSENT ) {
+ return false;
+ }
+ fitch7.setReturnInternalStates( true );
+ fitch7.setReturnGainLossMatrix( true );
+ fitch7.setUseLast( true );
+ fitch7.execute( p7, m7 );
+ final CharacterStateMatrix<GainLossStates> gl_m_71 = fitch7.getGainLossMatrix();
+ if ( fitch7.getCost() != 4 ) {
+ return false;
+ }
+ if ( fitch7.getTotalLosses() != 4 ) {
+ return false;
+ }
+ if ( fitch7.getTotalGains() != 0 ) {
+ return false;
+ }
+ if ( fitch7.getTotalUnchanged() != 11 ) {
+ return false;
+ }
+ if ( gl_m_71.getState( "b", "0" ) != LOSS ) {
+ return false;
+ }
+ if ( gl_m_71.getState( "d", "0" ) != LOSS ) {
+ return false;
+ }
+ if ( gl_m_71.getState( "f", "0" ) != LOSS ) {
+ return false;
+ }
+ if ( gl_m_71.getState( "h", "0" ) != LOSS ) {
+ return false;
+ }
+ if ( gl_m_71.getState( "r", "0" ) != UNCHANGED_PRESENT ) {
+ return false;
+ }
+ final FitchParsimony<BinaryStates> fitch8 = new FitchParsimony<BinaryStates>();
+ final PhylogenyFactory factory8 = ParserBasedPhylogenyFactory.getInstance();
+ final String p8_str = "(((a,b)ab,(c,d)cd)abcd,((e,f)ef,(g,h)gh)efgh)r";
+ final Phylogeny p8 = factory8.create( p8_str, new NHXParser() )[ 0 ];
+ final CharacterStateMatrix<BinaryStates> m8 = new BasicCharacterStateMatrix<BinaryStates>( 8, 1 );
+ m8.setIdentifier( 0, "a" );
+ m8.setIdentifier( 1, "b" );
+ m8.setIdentifier( 2, "c" );
+ m8.setIdentifier( 3, "d" );
+ m8.setIdentifier( 4, "e" );
+ m8.setIdentifier( 5, "f" );
+ m8.setIdentifier( 6, "g" );
+ m8.setIdentifier( 7, "h" );
+ m8.setCharacter( 0, "0" );
+ m8.setState( "a", "0", PRESENT );
+ m8.setState( "b", "0", PRESENT );
+ m8.setState( "c", "0", PRESENT );
+ m8.setState( "d", "0", ABSENT );
+ m8.setState( "e", "0", ABSENT );
+ m8.setState( "f", "0", ABSENT );
+ m8.setState( "g", "0", ABSENT );
+ m8.setState( "h", "0", ABSENT );
+ fitch8.setReturnInternalStates( true );
+ fitch8.setReturnGainLossMatrix( true );
+ fitch8.execute( p8, m8 );
+ final CharacterStateMatrix<GainLossStates> gl_m_8 = fitch8.getGainLossMatrix();
+ if ( fitch8.getCost() != 2 ) {
+ return false;
+ }
+ if ( fitch8.getTotalLosses() != 1 ) {
+ return false;
+ }
+ if ( fitch8.getTotalGains() != 1 ) {
+ return false;
+ }
+ if ( fitch8.getTotalUnchanged() != 13 ) {
+ return false;
+ }
+ if ( gl_m_8.getState( "d", "0" ) != LOSS ) {
+ return false;
+ }
+ if ( gl_m_8.getState( "abcd", "0" ) != GAIN ) {
+ return false;
+ }
+ final FitchParsimony<BinaryStates> fitch9 = new FitchParsimony<BinaryStates>();
+ final PhylogenyFactory factory9 = ParserBasedPhylogenyFactory.getInstance();
+ final String p9_str = "(((a,b)ab,c)abc,d)abcd";
+ final Phylogeny p9 = factory9.create( p9_str, new NHXParser() )[ 0 ];
+ final CharacterStateMatrix<BinaryStates> m9 = new BasicCharacterStateMatrix<BinaryStates>( 4, 1 );
+ m9.setIdentifier( 0, "a" );
+ m9.setIdentifier( 1, "b" );
+ m9.setIdentifier( 2, "c" );
+ m9.setIdentifier( 3, "d" );
+ m9.setCharacter( 0, "0" );
+ m9.setState( "a", "0", PRESENT );
+ m9.setState( "b", "0", ABSENT );
+ m9.setState( "c", "0", PRESENT );
+ m9.setState( "d", "0", ABSENT );
+ fitch9.setReturnInternalStates( true );
+ fitch9.setReturnGainLossMatrix( true );
+ fitch9.setUseLast( false );
+ fitch9.execute( p9, m9 );
+ final CharacterStateMatrix<GainLossStates> gl_m_9a = fitch9.getGainLossMatrix();
+ if ( fitch9.getCost() != 2 ) {
+ return false;
+ }
+ if ( fitch9.getTotalLosses() != 1 ) {
+ return false;
+ }
+ if ( fitch9.getTotalGains() != 1 ) {
+ return false;
+ }
+ if ( fitch9.getTotalUnchanged() != 5 ) {
+ return false;
+ }
+ if ( gl_m_9a.getState( "a", "0" ) != UNCHANGED_PRESENT ) {
+ return false;
+ }
+ if ( gl_m_9a.getState( "b", "0" ) != LOSS ) {
+ return false;
+ }
+ if ( gl_m_9a.getState( "c", "0" ) != UNCHANGED_PRESENT ) {
+ return false;
+ }
+ if ( gl_m_9a.getState( "d", "0" ) != UNCHANGED_ABSENT ) {
+ return false;
+ }
+ if ( gl_m_9a.getState( "ab", "0" ) != UNCHANGED_PRESENT ) {
+ return false;
+ }
+ if ( gl_m_9a.getState( "abc", "0" ) != GAIN ) {
+ return false;
+ }
+ if ( gl_m_9a.getState( "abcd", "0" ) != UNCHANGED_ABSENT ) {
+ return false;
+ }
+ fitch9.setUseLast( true );
+ fitch9.execute( p9, m9 );
+ final CharacterStateMatrix<GainLossStates> gl_m_9b = fitch9.getGainLossMatrix();
+ if ( fitch9.getCost() != 2 ) {
+ return false;
+ }
+ if ( fitch9.getTotalLosses() != 2 ) {
+ return false;
+ }
+ if ( fitch9.getTotalGains() != 0 ) {
+ return false;
+ }
+ if ( fitch9.getTotalUnchanged() != 5 ) {
+ return false;
+ }
+ if ( gl_m_9b.getState( "a", "0" ) != UNCHANGED_PRESENT ) {
+ return false;
+ }
+ if ( gl_m_9b.getState( "b", "0" ) != LOSS ) {
+ return false;
+ }
+ if ( gl_m_9b.getState( "c", "0" ) != UNCHANGED_PRESENT ) {
+ return false;
+ }
+ if ( gl_m_9b.getState( "d", "0" ) != LOSS ) {
+ return false;
+ }
+ if ( gl_m_9b.getState( "ab", "0" ) != UNCHANGED_PRESENT ) {
+ return false;
+ }
+ if ( gl_m_9b.getState( "abc", "0" ) != UNCHANGED_PRESENT ) {
+ return false;
+ }
+ if ( gl_m_9b.getState( "abcd", "0" ) != UNCHANGED_PRESENT ) {
+ return false;
+ }
+ fitch9.setUseLast( false );
+ fitch9.setRandomize( true );
+ fitch9.setRandomNumberSeed( 8722445 );
+ fitch9.execute( p9, m9 );
+ fitch9.getGainLossMatrix();
+ if ( fitch9.getCost() != 2 ) {
+ return false;
+ }
+ if ( fitch9.getTotalLosses() != 1 ) {
+ return false;
+ }
+ if ( fitch9.getTotalGains() != 1 ) {
+ return false;
+ }
+ if ( fitch9.getTotalUnchanged() != 5 ) {
+ return false;
+ }
+ final FitchParsimony<BinaryStates> fitch10 = new FitchParsimony<BinaryStates>();
+ final PhylogenyFactory factory10 = ParserBasedPhylogenyFactory.getInstance();
+ final String p10_str = "((((a,b)ab,c)abc,d)abcd,e)abcde";
+ final Phylogeny p10 = factory10.create( p10_str, new NHXParser() )[ 0 ];
+ final CharacterStateMatrix<BinaryStates> m10 = new BasicCharacterStateMatrix<BinaryStates>( 5, 1 );
+ m10.setIdentifier( 0, "a" );
+ m10.setIdentifier( 1, "b" );
+ m10.setIdentifier( 2, "c" );
+ m10.setIdentifier( 3, "d" );
+ m10.setIdentifier( 4, "e" );
+ m10.setCharacter( 0, "0" );
+ m10.setState( "a", "0", PRESENT );
+ m10.setState( "b", "0", ABSENT );
+ m10.setState( "c", "0", ABSENT );
+ m10.setState( "d", "0", PRESENT );
+ m10.setState( "e", "0", ABSENT );
+ fitch10.setReturnInternalStates( true );
+ fitch10.setReturnGainLossMatrix( true );
+ fitch10.setUseLast( false );
+ fitch10.execute( p10, m10 );
+ final CharacterStateMatrix<GainLossStates> gl_m_10a = fitch10.getGainLossMatrix();
+ if ( fitch10.getCost() != 2 ) {
+ return false;
+ }
+ if ( fitch10.getTotalLosses() != 0 ) {
+ return false;
+ }
+ if ( fitch10.getTotalGains() != 2 ) {
+ return false;
+ }
+ if ( fitch10.getTotalUnchanged() != 7 ) {
+ return false;
+ }
+ if ( gl_m_10a.getState( "a", "0" ) != GAIN ) {
+ return false;
+ }
+ if ( gl_m_10a.getState( "b", "0" ) != UNCHANGED_ABSENT ) {
+ return false;
+ }
+ if ( gl_m_10a.getState( "c", "0" ) != UNCHANGED_ABSENT ) {
+ return false;
+ }
+ if ( gl_m_10a.getState( "d", "0" ) != GAIN ) {
+ return false;
+ }
+ if ( gl_m_10a.getState( "e", "0" ) != UNCHANGED_ABSENT ) {
+ return false;
+ }
+ if ( gl_m_10a.getState( "ab", "0" ) != UNCHANGED_ABSENT ) {
+ return false;
+ }
+ if ( gl_m_10a.getState( "abc", "0" ) != UNCHANGED_ABSENT ) {
+ return false;
+ }
+ if ( gl_m_10a.getState( "abcd", "0" ) != UNCHANGED_ABSENT ) {
+ return false;
+ }
+ if ( gl_m_10a.getState( "abcde", "0" ) != UNCHANGED_ABSENT ) {
+ return false;
+ }
+ fitch10.setUseLast( true );
+ fitch10.execute( p10, m10 );
+ final CharacterStateMatrix<GainLossStates> gl_m_10b = fitch10.getGainLossMatrix();
+ if ( fitch10.getCost() != 2 ) {
+ return false;
+ }
+ if ( fitch10.getTotalLosses() != 0 ) {
+ return false;
+ }
+ if ( fitch10.getTotalGains() != 2 ) {
+ return false;
+ }
+ if ( fitch10.getTotalUnchanged() != 7 ) {
+ return false;
+ }
+ if ( gl_m_10b.getState( "a", "0" ) != GAIN ) {
+ return false;
+ }
+ if ( gl_m_10b.getState( "b", "0" ) != UNCHANGED_ABSENT ) {
+ return false;
+ }
+ if ( gl_m_10b.getState( "c", "0" ) != UNCHANGED_ABSENT ) {
+ return false;
+ }
+ if ( gl_m_10b.getState( "d", "0" ) != GAIN ) {
+ return false;
+ }
+ if ( gl_m_10b.getState( "e", "0" ) != UNCHANGED_ABSENT ) {
+ return false;
+ }
+ if ( gl_m_10b.getState( "ab", "0" ) != UNCHANGED_ABSENT ) {
+ return false;
+ }
+ if ( gl_m_10b.getState( "abc", "0" ) != UNCHANGED_ABSENT ) {
+ return false;
+ }
+ if ( gl_m_10b.getState( "abcd", "0" ) != UNCHANGED_ABSENT ) {
+ return false;
+ }
+ if ( gl_m_10b.getState( "abcde", "0" ) != UNCHANGED_ABSENT ) {
+ return false;
+ }
+ }
+ catch ( final Exception e ) {
+ e.printStackTrace( System.out );
+ return false;
+ }
+ return true;
+ }
+
+ private static boolean testNeighborJoining() {
+ try {
+ BasicSymmetricalDistanceMatrix m = new BasicSymmetricalDistanceMatrix( 6 );
+ m.setRow( "5", 1 );
+ m.setRow( "4 7", 2 );
+ m.setRow( "7 10 7", 3 );
+ m.setRow( "6 9 6 5", 4 );
+ m.setRow( "8 11 8 9 8", 5 );
+ m.setIdentifier( 0, "A" );
+ m.setIdentifier( 1, "B" );
+ m.setIdentifier( 2, "C" );
+ m.setIdentifier( 3, "D" );
+ m.setIdentifier( 4, "E" );
+ m.setIdentifier( 5, "F" );
+ final NeighborJoining nj = NeighborJoining.createInstance();
+ nj.setVerbose( false );
+ nj.execute( m );
+ m = new BasicSymmetricalDistanceMatrix( 7 );
+ m.setIdentifier( 0, "Bovine" );
+ m.setIdentifier( 1, "Mouse" );
+ m.setIdentifier( 2, "Gibbon" );
+ m.setIdentifier( 3, "Orang" );
+ m.setIdentifier( 4, "Gorilla" );
+ m.setIdentifier( 5, "Chimp" );
+ m.setIdentifier( 6, "Human" );
+ m.setRow( "0.00000 1.68660 1.71980 1.66060 1.52430 1.60430 1.59050", 0 );
+ m.setRow( "1.68660 0.00000 1.52320 1.48410 1.44650 1.43890 1.46290", 1 );
+ m.setRow( "1.71980 1.52320 0.00000 0.71150 0.59580 0.61790 0.55830", 2 );
+ m.setRow( "1.66060 1.48410 0.71150 0.00000 0.46310 0.50610 0.47100", 3 );
+ m.setRow( "1.52430 1.44650 0.59580 0.46310 0.00000 0.34840 0.30830", 4 );
+ m.setRow( "1.60430 1.43890 0.61790 0.50610 0.34840 0.00000 0.26920", 5 );
+ m.setRow( "1.59050 1.46290 0.55830 0.47100 0.30830 0.26920 0.00000", 6 );
+ nj.execute( m );
+ m = new BasicSymmetricalDistanceMatrix( 4 );
+ m.setIdentifier( 0, "A" );
+ m.setIdentifier( 1, "B" );
+ m.setIdentifier( 2, "C" );
+ m.setIdentifier( 3, "D" );
+ m.setRow( "0.00 0.95 0.17 0.98", 0 );
+ m.setRow( "0.95 0.00 1.02 1.83", 1 );
+ m.setRow( "0.17 1.02 0.00 1.01", 2 );
+ m.setRow( "0.98 1.83 1.01 0.00", 3 );
+ final Phylogeny p3 = nj.execute( m );
+ //
+ // -- A 0.05
+ // - |0.01
+ // ----------------------- B 0.90
+ //
+ // --- C 0.10
+ // - |0.01
+ // ------------------------- D 0.91
+ p3.reRoot( p3.getNode( "C" ).getParent() );
+ if ( !isEqual( p3.getNode( "A" ).getDistanceToParent(), 0.05 ) ) {
+ return false;
+ }
+ if ( !isEqual( p3.getNode( "B" ).getDistanceToParent(), 0.90 ) ) {
+ return false;
+ }
+ if ( !isEqual( p3.getNode( "C" ).getDistanceToParent(), 0.10 ) ) {
+ return false;
+ }
+ if ( !isEqual( p3.getNode( "D" ).getDistanceToParent(), 0.91 ) ) {
+ return false;
+ }
+ if ( TIME ) {
+ timeNeighborJoining();
+ }
+ }
+ catch ( final Exception e ) {
+ e.printStackTrace( System.out );
+ return false;
+ }
+ return true;
+ }
+
+ private static boolean testSymmetricalDistanceMatrixParser() {
+ try {
+ final String l = ForesterUtil.getLineSeparator();
+ StringBuffer source = new StringBuffer();
+ source.append( " 4" + l );
+ source.append( "A 0 0 0 0" + l );
+ source.append( "B 1 0 0 0" + l );
+ source.append( "C 2 4 0 0" + l );
+ source.append( "D 3 5 6 0" + l );
+ source.append( l );
+ source.append( " 4" + l );
+ source.append( "A 0 11 12 13" + l );
+ source.append( "B 11 0 14 15" + l );
+ source.append( "C 12 14 0 16" + l );
+ source.append( "D 13 15 16 0" + l );
+ source.append( l );
+ source.append( l );
+ source.append( " " + l );
+ source.append( " 4" + l );
+ source.append( " A 0 " + l );
+ source.append( " B 21 0" + l );
+ source.append( " C 22 24 0 " + l );
+ source.append( " # 2 222 2 2 " + l );
+ source.append( " D 23 25 26 0" + l );
+ source.append( l );
+ source.append( l );
+ source.append( " " + l );
+ final SymmetricalDistanceMatrixParser p0 = SymmetricalDistanceMatrixParser.createInstance();
+ final DistanceMatrix[] ma0 = p0.parse( source.toString() );
+ if ( ma0.length != 3 ) {
+ return false;
+ }
+ if ( !isEqual( ma0[ 0 ].getValue( 0, 0 ), 0 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma0[ 0 ].getValue( 1, 0 ), 1 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma0[ 0 ].getValue( 2, 0 ), 2 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma0[ 0 ].getValue( 3, 0 ), 3 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma0[ 0 ].getValue( 0, 1 ), 1 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma0[ 0 ].getValue( 1, 1 ), 0 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma0[ 0 ].getValue( 2, 1 ), 4 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma0[ 0 ].getValue( 3, 1 ), 5 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma0[ 1 ].getValue( 0, 0 ), 0 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma0[ 1 ].getValue( 1, 0 ), 11 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma0[ 1 ].getValue( 2, 0 ), 12 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma0[ 1 ].getValue( 3, 0 ), 13 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma0[ 1 ].getValue( 0, 1 ), 11 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma0[ 1 ].getValue( 1, 1 ), 0 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma0[ 1 ].getValue( 2, 1 ), 14 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma0[ 1 ].getValue( 3, 1 ), 15 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma0[ 2 ].getValue( 0, 0 ), 0 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma0[ 2 ].getValue( 1, 0 ), 21 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma0[ 2 ].getValue( 2, 0 ), 22 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma0[ 2 ].getValue( 3, 0 ), 23 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma0[ 2 ].getValue( 0, 1 ), 21 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma0[ 2 ].getValue( 1, 1 ), 0 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma0[ 2 ].getValue( 2, 1 ), 24 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma0[ 2 ].getValue( 3, 1 ), 25 ) ) {
+ return false;
+ }
+ source = new StringBuffer();
+ source.append( "A 0 0 0 0" + l );
+ source.append( "B 1 0 0 0" + l );
+ source.append( "C 2 4 0 0" + l );
+ source.append( "D 3 5 6 0" + l );
+ source.append( " " + l );
+ source.append( "A 0 11 12 13" + l );
+ source.append( "B 11 0 14 15" + l );
+ source.append( "C 12 14 0 16" + l );
+ source.append( "D 13 15 16 0" + l );
+ source.append( l );
+ source.append( " A 0 " + l );
+ source.append( " B 21 0" + l );
+ source.append( " C 22 24 0 " + l );
+ source.append( " # 2 222 2 2 " + l );
+ source.append( " D 23 25 26 0" + l );
+ final DistanceMatrix[] ma1 = p0.parse( source.toString() );
+ if ( ma1.length != 3 ) {
+ return false;
+ }
+ if ( !isEqual( ma1[ 0 ].getValue( 0, 0 ), 0 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma1[ 0 ].getValue( 1, 0 ), 1 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma1[ 0 ].getValue( 2, 0 ), 2 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma1[ 0 ].getValue( 3, 0 ), 3 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma1[ 0 ].getValue( 0, 1 ), 1 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma1[ 0 ].getValue( 1, 1 ), 0 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma1[ 0 ].getValue( 2, 1 ), 4 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma1[ 0 ].getValue( 3, 1 ), 5 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma1[ 1 ].getValue( 0, 0 ), 0 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma1[ 1 ].getValue( 1, 0 ), 11 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma1[ 1 ].getValue( 2, 0 ), 12 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma1[ 1 ].getValue( 3, 0 ), 13 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma1[ 1 ].getValue( 0, 1 ), 11 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma1[ 1 ].getValue( 1, 1 ), 0 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma1[ 1 ].getValue( 2, 1 ), 14 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma1[ 1 ].getValue( 3, 1 ), 15 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma1[ 2 ].getValue( 0, 0 ), 0 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma1[ 2 ].getValue( 1, 0 ), 21 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma1[ 2 ].getValue( 2, 0 ), 22 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma1[ 2 ].getValue( 3, 0 ), 23 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma1[ 2 ].getValue( 0, 1 ), 21 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma1[ 2 ].getValue( 1, 1 ), 0 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma1[ 2 ].getValue( 2, 1 ), 24 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma1[ 2 ].getValue( 3, 1 ), 25 ) ) {
+ return false;
+ }
+ source = new StringBuffer();
+ source.append( "A 0" + l );
+ source.append( "B 10 0" + l );
+ final DistanceMatrix[] ma2 = p0.parse( source.toString() );
+ if ( ma2.length != 1 ) {
+ return false;
+ }
+ if ( !isEqual( ma2[ 0 ].getValue( 0, 1 ), 10 ) ) {
+ return false;
+ }
+ source = new StringBuffer();
+ source.append( " " + l );
+ source.append( "#" + l );
+ final DistanceMatrix[] ma3 = p0.parse( source.toString() );
+ if ( ma3.length != 0 ) {
+ return false;
+ }
+ source = new StringBuffer();
+ source.append( " " + l );
+ source.append( "A 0 11 12 13" + l );
+ source.append( "B 0 14 15" + l );
+ source.append( "C 0 16" + l );
+ source.append( "D 0" + l );
+ source.append( l );
+ source.append( "A 0 21 22 23" + l );
+ source.append( "B 0 24 25" + l );
+ source.append( "C 0 26" + l );
+ source.append( "D 0" + l );
+ p0.setInputMatrixType( SymmetricalDistanceMatrixParser.InputMatrixType.UPPER_TRIANGLE );
+ final DistanceMatrix[] ma4 = p0.parse( source );
+ if ( ma4.length != 2 ) {
+ return false;
+ }
+ if ( !isEqual( ma4[ 0 ].getValue( 0, 0 ), 0 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma4[ 0 ].getValue( 1, 0 ), 11 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma4[ 0 ].getValue( 2, 0 ), 12 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma4[ 0 ].getValue( 3, 0 ), 13 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma4[ 0 ].getValue( 0, 1 ), 11 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma4[ 0 ].getValue( 1, 1 ), 0 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma4[ 0 ].getValue( 2, 1 ), 14 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma4[ 0 ].getValue( 3, 1 ), 15 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma4[ 0 ].getValue( 0, 2 ), 12 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma4[ 0 ].getValue( 1, 2 ), 14 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma4[ 0 ].getValue( 2, 2 ), 0 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma4[ 0 ].getValue( 3, 2 ), 16 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma4[ 0 ].getValue( 0, 3 ), 13 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma4[ 0 ].getValue( 1, 3 ), 15 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma4[ 0 ].getValue( 2, 3 ), 16 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma4[ 0 ].getValue( 3, 3 ), 0 ) ) {
+ return false;
+ }
+ source = new StringBuffer();
+ source.append( " 4 " + l );
+ source.append( "A 0 11 12 13" + l );
+ source.append( "B 0 14 15" + l );
+ source.append( "C 0 16" + l );
+ source.append( "D 0" + l );
+ source.append( " 4" + l );
+ source.append( "A 0 21 22 23" + l );
+ source.append( "B 0 24 25" + l );
+ source.append( "C 0 26" + l );
+ source.append( "D 0" + l );
+ source.append( " " + l );
+ source.append( " 4" + l );
+ source.append( "A 0 21 22 23" + l );
+ source.append( "B 0 24 25" + l );
+ source.append( "C 0 26" + l );
+ source.append( "D 0" + l );
+ source.append( l );
+ source.append( "A 0 21 22 23" + l );
+ source.append( "B 0 24 25" + l );
+ source.append( "C 0 26" + l );
+ source.append( "D 0" + l );
+ p0.setInputMatrixType( SymmetricalDistanceMatrixParser.InputMatrixType.UPPER_TRIANGLE );
+ final DistanceMatrix[] ma5 = p0.parse( source );
+ if ( ma5.length != 4 ) {
+ return false;
+ }
+ if ( !isEqual( ma5[ 0 ].getValue( 0, 0 ), 0 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma5[ 0 ].getValue( 1, 0 ), 11 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma5[ 0 ].getValue( 2, 0 ), 12 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma5[ 0 ].getValue( 3, 0 ), 13 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma5[ 0 ].getValue( 0, 1 ), 11 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma5[ 0 ].getValue( 1, 1 ), 0 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma5[ 0 ].getValue( 2, 1 ), 14 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma5[ 0 ].getValue( 3, 1 ), 15 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma5[ 0 ].getValue( 0, 2 ), 12 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma5[ 0 ].getValue( 1, 2 ), 14 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma5[ 0 ].getValue( 2, 2 ), 0 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma5[ 0 ].getValue( 3, 2 ), 16 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma5[ 0 ].getValue( 0, 3 ), 13 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma5[ 0 ].getValue( 1, 3 ), 15 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma5[ 0 ].getValue( 2, 3 ), 16 ) ) {
+ return false;
+ }
+ if ( !isEqual( ma5[ 0 ].getValue( 3, 3 ), 0 ) ) {
+ return false;
+ }
+ }
+ catch ( final Exception e ) {
+ e.printStackTrace( System.out );
+ return false;
+ }
+ return true;
+ }
+
+ private static void timeNeighborJoining() {
+ final NeighborJoining nj = NeighborJoining.createInstance();
+ for( int n = 3; n <= 12; ++n ) {
+ final int x = ( int ) Math.pow( 2, n );
+ final BasicSymmetricalDistanceMatrix mt = new BasicSymmetricalDistanceMatrix( x );
+ mt.randomize( new Date().getTime() );
+ final long start_time = new Date().getTime();
+ nj.execute( mt );
+ System.out.println( "Size: " + x + " -> " + ( new Date().getTime() - start_time ) + "ms." );
+ }
+ }
+}
--- /dev/null
+// $Id:
+// FORESTER -- software libraries and applications
+// for evolutionary biology research and applications.
+//
+// Copyright (C) 2008-2009 Christian M. Zmasek
+// Copyright (C) 2008-2009 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: www.phylosoft.org/forester
+
+package org.forester.evoinference.distance;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.forester.evoinference.matrix.distance.BasicSymmetricalDistanceMatrix;
+import org.forester.evoinference.matrix.distance.DistanceMatrix;
+import org.forester.phylogeny.Phylogeny;
+import org.forester.phylogeny.PhylogenyNode;
+import org.forester.phylogeny.PhylogenyNodeI;
+import org.forester.util.ForesterUtil;
+
+public class NeighborJoining {
+
+ private final static boolean VERBOSE_DEFAULT = false;
+ private DistanceMatrix _d;
+ private DistanceMatrix _m;
+ private double[] _r;
+ private int _n;
+ private PhylogenyNodeI[] _external_nodes;
+ private int[] _mappings;
+ private boolean _verbose;
+
+ public NeighborJoining() {
+ init();
+ }
+
+ private void calculateDistancesFromNewNode( final int otu1, final int otu2, final double d ) {
+ for( int i = 0; i < _n; ++i ) {
+ if ( ( i == otu1 ) || ( i == otu2 ) ) {
+ continue;
+ }
+ final double nd = ( getValueFromD( otu1, i ) + getValueFromD( i, otu2 ) - d ) / 2;
+ setValueInD( nd, otu1, i );
+ }
+ }
+
+ private double calculateM( final int i, final int j ) {
+ return getValueFromD( i, j ) - ( _r[ i ] + _r[ j ] ) / ( _n - 2 );
+ }
+
+ private void calculateNetDivergences() {
+ for( int i = 0; i < _n; ++i ) {
+ double d = 0.0;
+ for( int n = 0; n < _n; ++n ) {
+ d += getValueFromD( i, n );
+ }
+ _r[ i ] = d;
+ }
+ }
+
+ public Phylogeny execute( final DistanceMatrix distance ) {
+ reset( distance );
+ final Phylogeny phylogeny = new Phylogeny();
+ while ( _n > 2 ) {
+ updateM();
+ final int[] s = findMinimalDistance();
+ final int otu1 = s[ 0 ];
+ final int otu2 = s[ 1 ];
+ // It is a condition that otu1 < otu2.
+ if ( otu1 > otu2 ) {
+ throw new AssertionError( "NJ code is faulty: otu1 > otu2" );
+ }
+ final PhylogenyNodeI node = new PhylogenyNode();
+ final double d = getValueFromD( otu1, otu2 );
+ final double d1 = ( d / 2 ) + ( ( _r[ otu1 ] - _r[ otu2 ] ) / ( 2 * ( _n - 2 ) ) );
+ final double d2 = d - d1;
+ getExternalPhylogenyNode( otu1 ).setDistanceToParent( d1 );
+ getExternalPhylogenyNode( otu2 ).setDistanceToParent( d2 );
+ node.addAsChild( getExternalPhylogenyNode( otu1 ) );
+ node.addAsChild( getExternalPhylogenyNode( otu2 ) );
+ if ( isVerbose() ) {
+ printProgress( otu1, otu2 );
+ }
+ calculateDistancesFromNewNode( otu1, otu2, d );
+ setExternalPhylogenyNode( node, otu1 );
+ updateMappings( otu2 );
+ --_n;
+ }
+ final double d = getValueFromD( 0, 1 ) / 2;
+ getExternalPhylogenyNode( 0 ).setDistanceToParent( d );
+ getExternalPhylogenyNode( 1 ).setDistanceToParent( d );
+ final PhylogenyNodeI root = new PhylogenyNode();
+ root.addAsChild( getExternalPhylogenyNode( 0 ) );
+ root.addAsChild( getExternalPhylogenyNode( 1 ) );
+ if ( isVerbose() ) {
+ printProgress( 0, 1 );
+ }
+ phylogeny.setRoot( ( PhylogenyNode ) root );
+ phylogeny.setRooted( false );
+ return phylogeny;
+ }
+
+ public List<Phylogeny> execute( final List<DistanceMatrix> distances_list ) {
+ final List<Phylogeny> pl = new ArrayList<Phylogeny>();
+ for( final DistanceMatrix distances : distances_list ) {
+ pl.add( execute( distances ) );
+ }
+ return pl;
+ }
+
+ private int[] findMinimalDistance() {
+ // if more than one minimal distances, always the first found is
+ // returned
+ // i could randomize this, so that any would be returned in a randomized
+ // fashion...
+ double minimum = Double.MAX_VALUE;
+ int otu_1 = -1;
+ int otu_2 = -1;
+ for( int j = 1; j < _n; ++j ) {
+ for( int i = 0; i < j; ++i ) {
+ if ( _m.getValue( i, j ) < minimum ) {
+ minimum = _m.getValue( i, j );
+ otu_1 = i;
+ otu_2 = j;
+ }
+ }
+ }
+ return new int[] { otu_1, otu_2 };
+ }
+
+ private PhylogenyNodeI getExternalPhylogenyNode( final int i ) {
+ return _external_nodes[ _mappings[ i ] ];
+ }
+
+ private double getValueFromD( final int otu1, final int otu2 ) {
+ return _d.getValue( _mappings[ otu1 ], _mappings[ otu2 ] );
+ }
+
+ private void init() {
+ setVerbose( VERBOSE_DEFAULT );
+ }
+
+ private void initExternalNodes() {
+ _external_nodes = new PhylogenyNodeI[ _n ];
+ for( int i = 0; i < _n; ++i ) {
+ _external_nodes[ i ] = new PhylogenyNode();
+ final String id = _d.getIdentifier( i );
+ if ( id != null ) {
+ _external_nodes[ i ].setName( id );
+ }
+ else {
+ _external_nodes[ i ].setName( "" + i );
+ }
+ _mappings[ i ] = i;
+ }
+ }
+
+ private boolean isVerbose() {
+ return _verbose;
+ }
+
+ private void printProgress( final int otu1, final int otu2 ) {
+ final PhylogenyNodeI n1 = getExternalPhylogenyNode( otu1 );
+ final PhylogenyNodeI n2 = getExternalPhylogenyNode( otu2 );
+ System.out.println( "Node " + ( ForesterUtil.isEmpty( n1.getName() ) ? n1.getId() : n1.getName() ) + " joins "
+ + ( ForesterUtil.isEmpty( n2.getName() ) ? n2.getId() : n2.getName() ) );
+ }
+
+ // only the values in the lower triangle are used.
+ // !matrix values will be changed!
+ private void reset( final DistanceMatrix distances ) {
+ _n = distances.getSize();
+ _d = distances;
+ _m = new BasicSymmetricalDistanceMatrix( _n );
+ _r = new double[ _n ];
+ _mappings = new int[ _n ];
+ initExternalNodes();
+ }
+
+ private void setExternalPhylogenyNode( final PhylogenyNodeI node, final int i ) {
+ _external_nodes[ _mappings[ i ] ] = node;
+ }
+
+ private void setValueInD( final double d, final int otu1, final int otu2 ) {
+ _d.setValue( _mappings[ otu1 ], _mappings[ otu2 ], d );
+ }
+
+ public void setVerbose( final boolean verbose ) {
+ _verbose = verbose;
+ }
+
+ private void updateM() {
+ calculateNetDivergences();
+ for( int j = 1; j < _n; ++j ) {
+ for( int i = 0; i < j; ++i ) {
+ _m.setValue( i, j, calculateM( i, j ) );
+ }
+ }
+ }
+
+ // otu2 will, in effect, be "deleted" from the matrix.
+ private void updateMappings( final int otu2 ) {
+ for( int i = otu2; i < _mappings.length - 1; ++i ) {
+ _mappings[ i ] = _mappings[ i + 1 ];
+ }
+ }
+
+ public static NeighborJoining createInstance() {
+ return new NeighborJoining();
+ }
+}
--- /dev/null
+// $Id:
+// forester -- software libraries and applications
+// for genomics and evolutionary biology research.
+//
+// Copyright (C) 2010 Christian M Zmasek
+// Copyright (C) 2010 Sanford-Burnham Medical Research Institute
+// 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: www.phylosoft.org/forester
+
+package org.forester.evoinference.distance;
+
+import org.forester.evoinference.matrix.distance.BasicSymmetricalDistanceMatrix;
+import org.forester.msa.Msa;
+import org.forester.sequence.Sequence;
+
+public final class PairwiseDistanceCalculator {
+
+ public static final double DEFAULT_VALUE_FOR_TOO_LARGE_DISTANCE_FOR_KIMURA_FORMULA = 10; // Felsenstein uses -1
+ private static final char GAP = Sequence.GAP;
+ private final Msa _msa;
+ private final double _value_for_too_large_distance_for_kimura_formula;
+
+ private PairwiseDistanceCalculator( final Msa msa, final double value_for_too_large_distance_for_kimura_formula ) {
+ _msa = msa;
+ _value_for_too_large_distance_for_kimura_formula = value_for_too_large_distance_for_kimura_formula;
+ }
+
+ private double calcFractionalDissimilarity( final int row_1, final int row_2 ) {
+ final int length = _msa.getLength();
+ int nd = 0;
+ int n = 0;
+ char aa_1;
+ char aa_2;
+ for( int col = 0; col < length; ++col ) {
+ aa_1 = _msa.getResidueAt( row_1, col );
+ aa_2 = _msa.getResidueAt( row_2, col );
+ if ( ( aa_1 != GAP ) && ( aa_2 != GAP ) ) {
+ if ( aa_1 != aa_2 ) {
+ nd++;
+ }
+ n++;
+ }
+ }
+ if ( n == 0 ) {
+ return 1;
+ }
+ return ( double ) nd / n;
+ }
+
+ /**
+ * "Kimura Distance"
+ * Kimura, 1983
+ *
+ * @param row_1
+ * @param row_2
+ * @return
+ */
+ private double calcKimuraDistance( final int row_1, final int row_2 ) {
+ final double p = calcFractionalDissimilarity( row_1, row_2 );
+ final double dp = 1 - p - ( 0.2 * p * p );
+ if ( dp <= 0.0 ) {
+ return _value_for_too_large_distance_for_kimura_formula;
+ }
+ if ( dp == 1 ) {
+ return 0; // Too avoid -0.
+ }
+ return -Math.log( dp );
+ }
+
+ private double calcPoissonDistance( final int row_1, final int row_2 ) {
+ final double p = calcFractionalDissimilarity( row_1, row_2 );
+ final double dp = 1 - p;
+ if ( dp <= 0.0 ) {
+ return _value_for_too_large_distance_for_kimura_formula;
+ }
+ if ( dp == 1 ) {
+ return 0; // Too avoid -0.
+ }
+ return -Math.log( dp );
+ }
+
+ private BasicSymmetricalDistanceMatrix calcKimuraDistances() {
+ final int s = _msa.getNumberOfSequences();
+ final BasicSymmetricalDistanceMatrix d = new BasicSymmetricalDistanceMatrix( s );
+ copyIdentifiers( s, d );
+ calcKimuraDistances( s, d );
+ return d;
+ }
+
+ private BasicSymmetricalDistanceMatrix calcPoissonDistances() {
+ final int s = _msa.getNumberOfSequences();
+ final BasicSymmetricalDistanceMatrix d = new BasicSymmetricalDistanceMatrix( s );
+ copyIdentifiers( s, d );
+ calcPoissonDistances( s, d );
+ return d;
+ }
+
+ private BasicSymmetricalDistanceMatrix calcFractionalDissimilarities() {
+ final int s = _msa.getNumberOfSequences();
+ final BasicSymmetricalDistanceMatrix d = new BasicSymmetricalDistanceMatrix( s );
+ copyIdentifiers( s, d );
+ calcFractionalDissimilarities( s, d );
+ return d;
+ }
+
+ private void calcKimuraDistances( final int s, final BasicSymmetricalDistanceMatrix d ) {
+ for( int i = 1; i < s; i++ ) {
+ for( int j = 0; j < i; j++ ) {
+ d.setValue( i, j, calcKimuraDistance( i, j ) );
+ }
+ }
+ }
+
+ private void calcPoissonDistances( final int s, final BasicSymmetricalDistanceMatrix d ) {
+ for( int i = 1; i < s; i++ ) {
+ for( int j = 0; j < i; j++ ) {
+ d.setValue( i, j, calcPoissonDistance( i, j ) );
+ }
+ }
+ }
+
+ private void calcFractionalDissimilarities( final int s, final BasicSymmetricalDistanceMatrix d ) {
+ for( int i = 1; i < s; i++ ) {
+ for( int j = 0; j < i; j++ ) {
+ d.setValue( i, j, calcFractionalDissimilarity( i, j ) );
+ }
+ }
+ }
+
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ throw new CloneNotSupportedException();
+ }
+
+ private void copyIdentifiers( final int s, final BasicSymmetricalDistanceMatrix d ) {
+ for( int i = 0; i < s; i++ ) {
+ d.setIdentifier( i, ( String ) _msa.getIdentifier( i ) );
+ }
+ }
+
+ public static BasicSymmetricalDistanceMatrix calcFractionalDissimilarities( final Msa msa ) {
+ return new PairwiseDistanceCalculator( msa, DEFAULT_VALUE_FOR_TOO_LARGE_DISTANCE_FOR_KIMURA_FORMULA )
+ .calcFractionalDissimilarities();
+ }
+
+ public static BasicSymmetricalDistanceMatrix calcPoissonDistances( final Msa msa ) {
+ return new PairwiseDistanceCalculator( msa, DEFAULT_VALUE_FOR_TOO_LARGE_DISTANCE_FOR_KIMURA_FORMULA )
+ .calcPoissonDistances();
+ }
+
+ public static BasicSymmetricalDistanceMatrix calcKimuraDistances( final Msa msa ) {
+ return new PairwiseDistanceCalculator( msa, DEFAULT_VALUE_FOR_TOO_LARGE_DISTANCE_FOR_KIMURA_FORMULA )
+ .calcKimuraDistances();
+ }
+
+ public static BasicSymmetricalDistanceMatrix calcKimuraDistances( final Msa msa,
+ final double value_for_too_large_distance_for_kimura_formula ) {
+ return new PairwiseDistanceCalculator( msa, value_for_too_large_distance_for_kimura_formula )
+ .calcKimuraDistances();
+ }
+
+ public enum PWD_DISTANCE_METHOD {
+ KIMURA_DISTANCE, POISSON_DISTANCE, FRACTIONAL_DISSIMILARITY;
+ }
+}
--- /dev/null
+// $Id:
+// FORESTER -- software libraries and applications
+// for evolutionary biology research and applications.
+//
+// Copyright (C) 2008-2009 Christian M. Zmasek
+// Copyright (C) 2008-2009 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: www.phylosoft.org/forester
+
+package org.forester.evoinference.matrix.character;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.forester.io.parsers.nexus.NexusConstants;
+import org.forester.util.ForesterUtil;
+import org.forester.util.IllegalFormatUseException;
+
+public class BasicCharacterStateMatrix<S> implements CharacterStateMatrix<S> {
+
+ final Object[][] _states;
+ final String[] _identifiers;
+ final String[] _characters;
+ final Map<String, Integer> _identifier_index_map;
+ final Map<String, Integer> _character_index_map;
+
+ public BasicCharacterStateMatrix( final int number_of_identifiers, final int number_of_characters ) {
+ _states = new Object[ number_of_identifiers ][ number_of_characters ];
+ _identifiers = new String[ number_of_identifiers ];
+ _characters = new String[ number_of_characters ];
+ _identifier_index_map = new HashMap<String, Integer>( number_of_identifiers );
+ _character_index_map = new HashMap<String, Integer>( number_of_characters );
+ }
+
+ public BasicCharacterStateMatrix( final int number_of_identifiers,
+ final int number_of_characters,
+ final S default_state ) {
+ this( number_of_identifiers, number_of_identifiers );
+ for( int identifier = 0; identifier < number_of_identifiers; ++identifier ) {
+ for( int character = 0; character < number_of_characters; ++character ) {
+ setState( identifier, character, default_state );
+ }
+ }
+ }
+
+ public BasicCharacterStateMatrix( final List<List<S>> states ) {
+ if ( ( states == null ) || ( states.size() < 1 ) || ( states.get( 0 ) == null ) ) {
+ throw new IllegalArgumentException( "attempt to create character state matrix from empty list" );
+ }
+ final int number_of_characters = states.get( 0 ).size();
+ final int number_of_identifiers = states.size();
+ _states = new Object[ number_of_identifiers ][ number_of_characters ];
+ _identifiers = new String[ number_of_identifiers ];
+ _characters = new String[ number_of_characters ];
+ _identifier_index_map = new HashMap<String, Integer>( number_of_identifiers );
+ _character_index_map = new HashMap<String, Integer>( number_of_characters );
+ for( int identifier = 0; identifier < number_of_identifiers; ++identifier ) {
+ for( int character = 0; character < number_of_characters; ++character ) {
+ setState( identifier, character, states.get( identifier ).get( character ) );
+ }
+ }
+ }
+
+ public BasicCharacterStateMatrix( final S[][] states ) {
+ this( states.length, states[ 0 ].length );
+ for( int identifier = 0; identifier < states.length; ++identifier ) {
+ for( int character = 0; character < states[ 0 ].length; ++character ) {
+ setState( identifier, character, states[ identifier ][ character ] );
+ }
+ }
+ }
+
+ @Override
+ public boolean containsCharacter( final String character ) {
+ return _character_index_map.containsKey( character );
+ }
+
+ @Override
+ public boolean containsIdentifier( final String identifier ) {
+ return _identifier_index_map.containsKey( identifier );
+ }
+
+ public CharacterStateMatrix<S> copy() {
+ final CharacterStateMatrix<S> new_matrix = new BasicCharacterStateMatrix<S>( getNumberOfIdentifiers(),
+ getNumberOfCharacters() );
+ for( int character = 0; character < getNumberOfCharacters(); ++character ) {
+ if ( getCharacter( character ) != null ) {
+ new_matrix.setCharacter( character, getCharacter( character ) );
+ }
+ }
+ for( int identifier = 0; identifier < getNumberOfIdentifiers(); ++identifier ) {
+ if ( getIdentifier( identifier ) != null ) {
+ new_matrix.setIdentifier( identifier, getIdentifier( identifier ) );
+ }
+ for( int character = 0; character < getNumberOfCharacters(); ++character ) {
+ new_matrix.setState( identifier, character, getState( identifier, character ) );
+ }
+ }
+ return new_matrix;
+ }
+
+ @Override
+ public boolean equals( final Object o ) {
+ if ( this == o ) {
+ return true;
+ }
+ else if ( o == null ) {
+ throw new IllegalArgumentException( "attempt to check character state matrix equality to null" );
+ }
+ else if ( o.getClass() != this.getClass() ) {
+ throw new IllegalArgumentException( "attempt to check character state matrix to " + o + " [" + o.getClass()
+ + "]" );
+ }
+ else {
+ final CharacterStateMatrix<S> other = ( CharacterStateMatrix<S> ) o;
+ if ( ( getNumberOfIdentifiers() != other.getNumberOfIdentifiers() )
+ || ( getNumberOfCharacters() != other.getNumberOfCharacters() ) ) {
+ }
+ for( int identifier = 0; identifier < getNumberOfIdentifiers(); ++identifier ) {
+ for( int character = 0; character < getNumberOfCharacters(); ++character ) {
+ final S s = getState( identifier, character );
+ final S os = other.getState( identifier, character );
+ if ( s == os ) {
+ continue;
+ }
+ else if ( ( s == null ) && ( os != null ) ) {
+ return false;
+ }
+ else if ( ( s != null ) && ( os == null ) ) {
+ return false;
+ }
+ else if ( !s.equals( other.getState( identifier, character ) ) ) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+ }
+
+ @Override
+ public String getCharacter( final int character_index ) {
+ return _characters[ character_index ];
+ }
+
+ @Override
+ public int getCharacterIndex( final String character ) {
+ if ( !_character_index_map.containsKey( character ) ) {
+ throw new IllegalArgumentException( "character [" + character + "] not found" );
+ }
+ return _character_index_map.get( character );
+ }
+
+ @Override
+ public String getIdentifier( final int identifier_index ) {
+ return _identifiers[ identifier_index ];
+ }
+
+ @Override
+ public int getIdentifierIndex( final String identifier ) {
+ if ( !_identifier_index_map.containsKey( identifier ) ) {
+ throw new IllegalArgumentException( "indentifier [" + identifier + "] not found" );
+ }
+ return _identifier_index_map.get( identifier );
+ }
+
+ private int getLengthOfLongestState() {
+ int longest = 0;
+ for( int identifier = 0; identifier < getNumberOfIdentifiers(); ++identifier ) {
+ for( int character = 0; character < getNumberOfCharacters(); ++character ) {
+ final S s = getState( identifier, character );
+ if ( s != null ) {
+ final int l = getState( identifier, character ).toString().length();
+ if ( l > longest ) {
+ longest = l;
+ }
+ }
+ }
+ }
+ return longest;
+ }
+
+ @Override
+ public int getNumberOfCharacters() {
+ if ( !isEmpty() ) {
+ return _states[ 0 ].length;
+ }
+ else {
+ return 0;
+ }
+ }
+
+ @Override
+ public int getNumberOfIdentifiers() {
+ return _states.length;
+ }
+
+ @Override
+ public S getState( final int identifier_index, final int character_index ) {
+ return ( S ) _states[ identifier_index ][ character_index ];
+ }
+
+ @Override
+ public S getState( final String identifier, final int character_index ) {
+ if ( !containsIdentifier( identifier ) ) {
+ throw new IllegalArgumentException( "identifier [" + identifier + "] not found" );
+ }
+ return getState( _identifier_index_map.get( identifier ), character_index );
+ }
+
+ @Override
+ public S getState( final String identifier, final String character ) {
+ if ( !containsIdentifier( identifier ) ) {
+ throw new IllegalArgumentException( "identifier [" + identifier + "] not found" );
+ }
+ if ( !containsCharacter( character ) ) {
+ throw new IllegalArgumentException( "character [" + character + "] not found" );
+ }
+ return getState( _identifier_index_map.get( identifier ), _character_index_map.get( character ) );
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return getNumberOfIdentifiers() <= 0;
+ }
+
+ public CharacterStateMatrix<S> pivot() {
+ final CharacterStateMatrix<S> new_matrix = new BasicCharacterStateMatrix<S>( getNumberOfCharacters(),
+ getNumberOfIdentifiers() );
+ for( int character = 0; character < getNumberOfCharacters(); ++character ) {
+ if ( getCharacter( character ) != null ) {
+ new_matrix.setIdentifier( character, getCharacter( character ) );
+ }
+ }
+ for( int identifier = 0; identifier < getNumberOfIdentifiers(); ++identifier ) {
+ if ( getIdentifier( identifier ) != null ) {
+ new_matrix.setCharacter( identifier, getIdentifier( identifier ) );
+ }
+ for( int character = 0; character < getNumberOfCharacters(); ++character ) {
+ new_matrix.setState( character, identifier, getState( identifier, character ) );
+ }
+ }
+ return new_matrix;
+ }
+
+ @Override
+ public void setCharacter( final int character_index, final String character ) {
+ if ( character == null ) {
+ throw new IllegalArgumentException( "attempt to use null character" );
+ }
+ _characters[ character_index ] = character;
+ if ( _character_index_map.containsKey( character ) ) {
+ throw new IllegalArgumentException( "character [" + character + "] is not unique" );
+ }
+ _character_index_map.put( character, character_index );
+ }
+
+ @Override
+ public void setIdentifier( final int identifier_index, final String identifier ) {
+ if ( identifier == null ) {
+ throw new IllegalArgumentException( "attempt to use null identifier" );
+ }
+ _identifiers[ identifier_index ] = identifier;
+ if ( _identifier_index_map.containsKey( identifier ) ) {
+ throw new IllegalArgumentException( "identifier [" + identifier + "] is not unique" );
+ }
+ _identifier_index_map.put( identifier, identifier_index );
+ }
+
+ @Override
+ public void setState( final int identifier_index, final int character_index, final S state ) {
+ _states[ identifier_index ][ character_index ] = state;
+ }
+
+ @Override
+ public void setState( final String identifier, final int character_index, final S state ) {
+ if ( !_identifier_index_map.containsKey( identifier ) ) {
+ throw new IllegalArgumentException( "identifier [" + identifier + "] not found" );
+ }
+ setState( _identifier_index_map.get( identifier ), character_index, state );
+ }
+
+ @Override
+ public void setState( final String identifier, final String character, final S state ) {
+ if ( !containsIdentifier( identifier ) ) {
+ throw new IllegalArgumentException( "identifier [" + identifier + "] not found" );
+ }
+ if ( !containsCharacter( character ) ) {
+ throw new IllegalArgumentException( "character [" + character + "] not found" );
+ }
+ setState( _identifier_index_map.get( identifier ), _character_index_map.get( character ), state );
+ }
+
+ private void toForester( final Writer writer ) throws IOException {
+ final int longest = getLengthOfLongestState() + 5;
+ writer.write( "Identifiers: " );
+ writer.write( String.valueOf( getNumberOfIdentifiers() ) );
+ writer.write( ForesterUtil.LINE_SEPARATOR );
+ writer.write( "Characters : " );
+ writer.write( String.valueOf( getNumberOfCharacters() ) );
+ writer.write( ForesterUtil.LINE_SEPARATOR );
+ writer.write( ForesterUtil.pad( "", 20, ' ', false ).toString() );
+ writer.write( ' ' );
+ for( int character = 0; character < getNumberOfCharacters(); ++character ) {
+ final String c = getCharacter( character );
+ writer.write( c != null ? ForesterUtil.pad( c, longest, ' ', false ).toString() : ForesterUtil
+ .pad( "", longest, ' ', false ).toString() );
+ if ( character < getNumberOfCharacters() - 1 ) {
+ writer.write( ' ' );
+ }
+ }
+ writer.write( ForesterUtil.LINE_SEPARATOR );
+ for( int identifier = 0; identifier < getNumberOfIdentifiers(); ++identifier ) {
+ if ( getIdentifier( identifier ) != null ) {
+ writer.write( ForesterUtil.pad( getIdentifier( identifier ), 20, ' ', false ).toString() );
+ writer.write( ' ' );
+ }
+ for( int character = 0; character < getNumberOfCharacters(); ++character ) {
+ final S state = getState( identifier, character );
+ writer.write( state != null ? ForesterUtil.pad( state.toString(), longest, ' ', false ).toString()
+ : ForesterUtil.pad( "", longest, ' ', false ).toString() );
+ if ( character < getNumberOfCharacters() - 1 ) {
+ writer.write( ' ' );
+ }
+ }
+ if ( identifier < getNumberOfIdentifiers() - 1 ) {
+ writer.write( ForesterUtil.LINE_SEPARATOR );
+ }
+ }
+ }
+
+ private void toNexus( final Writer writer ) throws IOException {
+ if ( isEmpty() ) {
+ return;
+ }
+ writer.write( NexusConstants.NEXUS );
+ writer.write( ForesterUtil.LINE_SEPARATOR );
+ writeNexusTaxaBlock( writer );
+ writeNexusBinaryChractersBlock( writer );
+ }
+
+ private void toPhylip( final Writer writer ) throws IOException {
+ final int pad = 6;
+ writer.write( ' ' );
+ writer.write( ' ' );
+ writer.write( ' ' );
+ writer.write( ' ' );
+ writer.write( getNumberOfIdentifiers() );
+ writer.write( ' ' );
+ writer.write( getNumberOfCharacters() );
+ writer.write( ForesterUtil.LINE_SEPARATOR );
+ for( int identifier = 0; identifier < getNumberOfIdentifiers(); ++identifier ) {
+ if ( !ForesterUtil.isEmpty( getIdentifier( identifier ) ) ) {
+ writer.write( ForesterUtil.pad( getIdentifier( identifier ), pad, ' ', false ).toString() );
+ writer.write( ' ' );
+ writer.write( ' ' );
+ }
+ else {
+ throw new IllegalFormatUseException( "Phylip format does not allow empty identifiers" );
+ }
+ writer.write( "" );
+ for( int character = 0; character < getNumberOfCharacters(); ++character ) {
+ final String state = getState( identifier, character ).toString();
+ writer.write( state != null ? ForesterUtil.pad( state, pad, ' ', false ).toString() : ForesterUtil
+ .pad( "", pad, ' ', false ).toString() );
+ if ( character < getNumberOfCharacters() - 1 ) {
+ writer.write( ' ' );
+ writer.write( ' ' );
+ }
+ }
+ if ( identifier < getNumberOfIdentifiers() - 1 ) {
+ writer.write( ForesterUtil.LINE_SEPARATOR );
+ }
+ }
+ }
+
+ //TODO
+ //to format for microarray-style clustering
+ // states are ints in this case
+ //TODO
+ public void toWriter( final Writer writer ) throws IOException {
+ toForester( writer );
+ }
+
+ @Override
+ public void toWriter( final Writer writer, final Format format ) throws IOException {
+ switch ( format ) {
+ case PHYLIP:
+ toPhylip( writer );
+ break;
+ case FORESTER:
+ toForester( writer );
+ break;
+ case NEXUS_BINARY:
+ toNexus( writer );
+ break;
+ default:
+ throw new IllegalArgumentException( "Unknown format:" + format );
+ }
+ }
+
+ public void writeNexusBinaryChractersBlock( final Writer w ) throws IOException {
+ //BEGIN CHARACTERS;
+ // DIMENSIONS NCHAR=x;
+ //BEGIN CHARSTATELABELS
+ // 1 bcl,
+ // 2 tir,
+ //END;
+ // FORMAT DATATYPE=STANDARD SYMBOLS=;
+ // MATRIX
+ // fish d d f
+ // frog s d f f
+ // snake x x x x;
+ // END;
+ w.write( NexusConstants.BEGIN_CHARACTERS );
+ w.write( ForesterUtil.LINE_SEPARATOR );
+ w.write( " " );
+ w.write( NexusConstants.DIMENSIONS );
+ w.write( " " );
+ w.write( NexusConstants.NCHAR );
+ w.write( "=" );
+ w.write( String.valueOf( getNumberOfCharacters() ) );
+ w.write( ";" );
+ w.write( ForesterUtil.LINE_SEPARATOR );
+ writeNexusCharstatelabels( w );
+ w.write( " " );
+ w.write( NexusConstants.FORMAT );
+ w.write( " " );
+ w.write( NexusConstants.DATATYPE );
+ w.write( "=" );
+ w.write( NexusConstants.STANDARD );
+ w.write( " " );
+ w.write( NexusConstants.SYMBOLS );
+ w.write( "=\"" );
+ w.write( String.valueOf( BinaryStates.ABSENT ) );
+ w.write( String.valueOf( BinaryStates.PRESENT ) );
+ w.write( "\";" );
+ w.write( ForesterUtil.LINE_SEPARATOR );
+ writeNexusMatrix( w );
+ w.write( ForesterUtil.LINE_SEPARATOR );
+ w.write( NexusConstants.END );
+ w.write( ForesterUtil.LINE_SEPARATOR );
+ }
+
+ public void writeNexusCharstatelabels( final Writer w ) throws IOException {
+ w.write( " " );
+ w.write( NexusConstants.CHARSTATELABELS );
+ w.write( ForesterUtil.LINE_SEPARATOR );
+ for( int i = 0; i < getNumberOfCharacters(); ++i ) {
+ w.write( " " + ( i + 1 ) + " '" );
+ w.write( getCharacter( i ) );
+ w.write( "'" );
+ if ( i < getNumberOfCharacters() - 1 ) {
+ w.write( "," );
+ w.write( ForesterUtil.LINE_SEPARATOR );
+ }
+ }
+ w.write( ";" );
+ w.write( ForesterUtil.LINE_SEPARATOR );
+ }
+
+ public void writeNexusMatrix( final Writer w ) throws IOException {
+ w.write( " " );
+ w.write( NexusConstants.MATRIX );
+ w.write( ForesterUtil.LINE_SEPARATOR );
+ for( int identifier = 0; identifier < getNumberOfIdentifiers(); ++identifier ) {
+ if ( getIdentifier( identifier ) != null ) {
+ w.write( " " );
+ w.write( ForesterUtil.pad( getIdentifier( identifier ), 20, ' ', false ).toString() );
+ w.write( ' ' );
+ }
+ for( int character = 0; character < getNumberOfCharacters(); ++character ) {
+ final S state = getState( identifier, character );
+ if ( state == null ) {
+ throw new IllegalFormatUseException( "character state matrix cannot contain null if to be represented in nexus format" );
+ }
+ if ( !( state instanceof BinaryStates ) ) {
+ throw new IllegalFormatUseException( "nexus format representation expects binary character data - got ["
+ + getState( 0, 0 ).getClass() + "] instead" );
+ }
+ if ( state == BinaryStates.UNKNOWN ) {
+ throw new IllegalFormatUseException( "character state matrix cannot contain unknown states if to be represented in nexus format" );
+ }
+ w.write( state.toString() );
+ }
+ if ( identifier < getNumberOfIdentifiers() - 1 ) {
+ w.write( ForesterUtil.LINE_SEPARATOR );
+ }
+ }
+ w.write( ";" );
+ }
+
+ public void writeNexusTaxaBlock( final Writer w ) throws IOException {
+ //BEGIN TAXA;
+ // DIMENSIONS NTAX=n;
+ // TAXLABELS fish frog snake;
+ //END;
+ w.write( NexusConstants.BEGIN_TAXA );
+ w.write( ForesterUtil.LINE_SEPARATOR );
+ w.write( " " );
+ w.write( NexusConstants.DIMENSIONS );
+ w.write( " " );
+ w.write( NexusConstants.NTAX );
+ w.write( "=" );
+ w.write( String.valueOf( getNumberOfIdentifiers() ) );
+ w.write( ";" );
+ w.write( ForesterUtil.LINE_SEPARATOR );
+ w.write( " " );
+ w.write( NexusConstants.TAXLABELS );
+ for( int i = 0; i < getNumberOfIdentifiers(); ++i ) {
+ w.write( " " );
+ w.write( getIdentifier( i ) );
+ }
+ w.write( ";" );
+ w.write( ForesterUtil.LINE_SEPARATOR );
+ w.write( NexusConstants.END );
+ w.write( ForesterUtil.LINE_SEPARATOR );
+ }
+}
--- /dev/null
+// $Id:
+// FORESTER -- software libraries and applications
+// for evolutionary biology research and applications.
+//
+// Copyright (C) 2008-2009 Christian M. Zmasek
+// Copyright (C) 2008-2009 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: www.phylosoft.org/forester
+
+package org.forester.evoinference.matrix.character;
+
+import java.io.IOException;
+import java.io.Writer;
+
+public interface CharacterStateMatrix<S> {
+
+ public boolean containsCharacter( final String character );
+
+ public boolean containsIdentifier( final String identifier );
+
+ public CharacterStateMatrix<S> copy();
+
+ public String getCharacter( int character_index );
+
+ public int getCharacterIndex( final String character );
+
+ public String getIdentifier( int identifier_index );
+
+ public int getIdentifierIndex( final String identifier );
+
+ public int getNumberOfCharacters();
+
+ public int getNumberOfIdentifiers();
+
+ public S getState( final int identifier_index, final int character_index );
+
+ public S getState( final String identifier, final int character_index );
+
+ public S getState( final String identifier, final String character );
+
+ public boolean isEmpty();
+
+ public CharacterStateMatrix<S> pivot();
+
+ public void setCharacter( int character_index, final String character );
+
+ public void setIdentifier( int identifier_index, final String identifier );
+
+ public void setState( int identifier_index, int character_index, final S state );
+
+ public void setState( final String identifier, int character_index, final S state );
+
+ public void setState( final String identifier, final String character, final S state );
+
+ public void toWriter( final Writer writer ) throws IOException;
+
+ public void toWriter( final Writer writer, final Format format ) throws IOException;
+
+ /**
+ * It is crucial that the order
+ * ABSENT, UNKNOWN, PRESENT not be changes since
+ * this determines the sort order.
+ *
+ */
+ static public enum BinaryStates {
+ ABSENT, UNKNOWN, PRESENT;
+
+ public char toChar() {
+ switch ( this ) {
+ case PRESENT:
+ return '1';
+ case ABSENT:
+ return '0';
+ case UNKNOWN:
+ return '?';
+ }
+ throw new RuntimeException( "unknown state: " + this );
+ }
+
+ @Override
+ public String toString() {
+ switch ( this ) {
+ case PRESENT:
+ return "1";
+ case ABSENT:
+ return "0";
+ case UNKNOWN:
+ return "?";
+ }
+ throw new RuntimeException( "unknown state: " + this );
+ }
+ }
+
+ public static enum Format {
+ PHYLIP, FORESTER, NEXUS_BINARY
+ }
+
+ static public enum GainLossStates {
+ GAIN, LOSS, UNCHANGED_PRESENT, UNCHANGED_ABSENT, UNKNOWN;
+
+ @Override
+ public String toString() {
+ switch ( this ) {
+ case GAIN:
+ return "+";
+ case LOSS:
+ return "-";
+ case UNCHANGED_PRESENT:
+ return "X";
+ case UNCHANGED_ABSENT:
+ return ".";
+ case UNKNOWN:
+ return "?";
+ }
+ throw new AssertionError( "unknown state: " + this );
+ }
+ }
+
+ static public enum NucleotideStates {
+ A, C, G, T, UNKNOWN;
+ }
+}
--- /dev/null
+// $Id:
+//
+// FORESTER -- software libraries and applications
+// for evolutionary biology research and applications.
+//
+// Copyright (C) 2008-2009 Christian M. Zmasek
+// Copyright (C) 2008-2009 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: www.phylosoft.org/forester
+
+package org.forester.evoinference.matrix.character;
+
+import org.forester.util.ForesterUtil;
+
+public class DiscreteState implements Comparable<DiscreteState> {
+
+ final private String _id;
+
+ public DiscreteState( final String id ) {
+ if ( ForesterUtil.isEmpty( id ) ) {
+ throw new IllegalArgumentException( "attempt to create new discrete state from empty or null string" );
+ }
+ _id = id.trim();
+ }
+
+ @Override
+ public int compareTo( final DiscreteState discrete_state ) {
+ if ( this == discrete_state ) {
+ return 0;
+ }
+ return getId().compareTo( discrete_state.getId() );
+ }
+
+ @Override
+ public boolean equals( final Object o ) {
+ if ( this == o ) {
+ return true;
+ }
+ else if ( o == null ) {
+ throw new IllegalArgumentException( "attempt to check discrete state equality to null" );
+ }
+ else if ( o.getClass() != this.getClass() ) {
+ throw new IllegalArgumentException( "attempt to check discrete stateequality to " + o + " [" + o.getClass()
+ + "]" );
+ }
+ else {
+ return getId().equals( ( ( DiscreteState ) o ).getId() );
+ }
+ }
+
+ public String getId() {
+ return _id;
+ }
+
+ @Override
+ public int hashCode() {
+ return getId().hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return getId();
+ }
+}
\ No newline at end of file
--- /dev/null
+// $Id:
+// Exp $
+// FORESTER -- software libraries and applications
+// for evolutionary biology research and applications.
+//
+// Copyright (C) 2008-2009 Christian M. Zmasek
+// Copyright (C) 2008-2009 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: www.phylosoft.org/forester
+
+package org.forester.evoinference.matrix.distance;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.text.DecimalFormat;
+import java.text.NumberFormat;
+import java.util.StringTokenizer;
+
+import org.forester.util.ForesterUtil;
+import org.forester.util.IllegalFormatUseException;
+
+public class BasicSymmetricalDistanceMatrix implements DistanceMatrix {
+
+ NumberFormat nf1 = NumberFormat.getInstance();
+ private final static NumberFormat PHYLIP_FORMATTER = new DecimalFormat( "0.000000" );
+ final double[][] _values;
+ final String[] _identifiers;
+
+ public BasicSymmetricalDistanceMatrix( final int size ) {
+ _values = new double[ size ][ size ];
+ _identifiers = new String[ size ];
+ }
+
+ public String getIdentifier( final int i ) {
+ return _identifiers[ i ];
+ }
+
+ public int getIndex( final String identifier ) {
+ for( int i = 0; i < _identifiers.length; i++ ) {
+ if ( getIdentifier( i ).equals( identifier ) ) {
+ return i;
+ }
+ }
+ throw new IllegalArgumentException( "identifier [" + identifier + "] not found in distance matrix" );
+ }
+
+ public int getSize() {
+ return _values.length;
+ }
+
+ public double getValue( final int col, final int row ) {
+ if ( col == row ) {
+ if ( col >= getSize() ) {
+ throw new IndexOutOfBoundsException( "" );
+ }
+ return 0.0;
+ }
+ else if ( col > row ) {
+ return _values[ row ][ col ];
+ }
+ return _values[ col ][ row ];
+ }
+
+ public void randomize( final long seed ) {
+ final java.util.Random r = new java.util.Random( seed );
+ for( int j = 0; j < getSize(); ++j ) {
+ for( int i = 0; i < j; ++i ) {
+ setValue( i, j, r.nextDouble() );
+ }
+ }
+ }
+
+ public void setIdentifier( final int i, final String identifier ) {
+ _identifiers[ i ] = identifier;
+ }
+
+ public void setRow( final String s, final int row ) {
+ final StringTokenizer tk = new StringTokenizer( s );
+ int i = 0;
+ while ( tk.hasMoreElements() ) {
+ setValue( i, row, new Double( tk.nextToken() ).doubleValue() );
+ i++;
+ }
+ }
+
+ public void setValue( final int col, final int row, final double d ) {
+ if ( ( col == row ) && ( d != 0.0 ) ) {
+ throw new IllegalArgumentException( "attempt to set a non-zero value on the diagonal of a symmetrical distance matrix" );
+ }
+ else if ( col > row ) {
+ _values[ row ][ col ] = d;
+ }
+ _values[ col ][ row ] = d;
+ }
+
+ public void write( final Writer w ) throws IOException {
+ w.write( " " );
+ w.write( getSize() + "" );
+ w.write( ForesterUtil.LINE_SEPARATOR );
+ for( int row = 0; row < getSize(); ++row ) {
+ if ( !ForesterUtil.isEmpty( getIdentifier( row ) ) ) {
+ w.write( ForesterUtil.pad( getIdentifier( row ), 10, ' ', false ).toString() );
+ w.write( ' ' );
+ w.write( ' ' );
+ }
+ else {
+ throw new IllegalFormatUseException( "Phylip format does not allow empty identifiers" );
+ }
+ for( int col = 0; col < getSize(); ++col ) {
+ w.write( PHYLIP_FORMATTER.format( getValue( col, row ) ) );
+ if ( col < getSize() - 1 ) {
+ w.write( ' ' );
+ w.write( ' ' );
+ }
+ }
+ if ( row < getSize() - 1 ) {
+ w.write( ForesterUtil.LINE_SEPARATOR );
+ }
+ }
+ }
+
+ private StringBuffer toPhylip() {
+ final StringBuffer sb = new StringBuffer();
+ sb.append( ' ' );
+ sb.append( ' ' );
+ sb.append( ' ' );
+ sb.append( ' ' );
+ sb.append( getSize() );
+ sb.append( ForesterUtil.LINE_SEPARATOR );
+ for( int row = 0; row < getSize(); ++row ) {
+ if ( !ForesterUtil.isEmpty( getIdentifier( row ) ) ) {
+ sb.append( ForesterUtil.pad( getIdentifier( row ), 10, ' ', false ) );
+ sb.append( ' ' );
+ sb.append( ' ' );
+ }
+ else {
+ throw new IllegalFormatUseException( "Phylip format does not allow empty identifiers" );
+ }
+ //sb.append( "" );
+ for( int col = 0; col < getSize(); ++col ) {
+ sb.append( PHYLIP_FORMATTER.format( getValue( col, row ) ) );
+ if ( col < getSize() - 1 ) {
+ sb.append( ' ' );
+ sb.append( ' ' );
+ }
+ }
+ if ( row < getSize() - 1 ) {
+ sb.append( ForesterUtil.LINE_SEPARATOR );
+ }
+ }
+ return sb;
+ }
+
+ @Override
+ public String toString() {
+ return toPhylip().toString();
+ }
+
+ public StringBuffer toStringBuffer( final Format format ) {
+ switch ( format ) {
+ case PHYLIP:
+ return toPhylip();
+ default:
+ throw new IllegalArgumentException( "Unknown format:" + format );
+ }
+ }
+}
--- /dev/null
+// $Id:
+// FORESTER -- software libraries and applications
+// for evolutionary biology research and applications.
+//
+// Copyright (C) 2008-2009 Christian M. Zmasek
+// Copyright (C) 2008-2009 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: www.phylosoft.org/forester
+
+package org.forester.evoinference.matrix.distance;
+
+public interface DistanceMatrix {
+
+ public String getIdentifier( int i );
+
+ public int getIndex( String identifier );
+
+ public int getSize();
+
+ public double getValue( int col, int row );
+
+ public void setIdentifier( int i, final String identifier );
+
+ public void setValue( int col, int row, double distance );
+
+ public StringBuffer toStringBuffer( Format format );
+
+ public static enum Format {
+ PHYLIP
+ }
+}
--- /dev/null
+// $Id:
+//
+// FORESTER -- software libraries and applications
+// for evolutionary biology research and applications.
+//
+// Copyright (C) 2008-2009 Christian M. Zmasek
+// Copyright (C) 2008-2009 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: www.phylosoft.org/forester
+
+package org.forester.evoinference.parsimony;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+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.evoinference.matrix.character.CharacterStateMatrix.GainLossStates;
+import org.forester.phylogeny.Phylogeny;
+import org.forester.phylogeny.PhylogenyNode;
+import org.forester.phylogeny.iterators.PhylogenyNodeIterator;
+import org.forester.util.ForesterUtil;
+
+public class DolloParsimony {
+
+ final static private BinaryStates PRESENT = BinaryStates.PRESENT;
+ final static private BinaryStates ABSENT = BinaryStates.ABSENT;
+ final static private BinaryStates UNKNOWN = BinaryStates.UNKNOWN;
+ final static private GainLossStates LOSS = GainLossStates.LOSS;
+ final static private GainLossStates GAIN = GainLossStates.GAIN;
+ final static private GainLossStates UNCHANGED_PRESENT = GainLossStates.UNCHANGED_PRESENT;
+ final static private GainLossStates UNCHANGED_ABSENT = GainLossStates.UNCHANGED_ABSENT;
+ private static final boolean RETURN_INTERNAL_STATES_DEFAULT = false;
+ private static final boolean RETURN_GAIN_LOSS_MATRIX_DEFAULT = false;
+ private boolean _return_internal_states = false;
+ private boolean _return_gain_loss = false;
+ private int _total_gains;
+ private int _total_losses;
+ private int _total_unchanged;
+ private CharacterStateMatrix<BinaryStates> _internal_states_matrix;
+ private CharacterStateMatrix<GainLossStates> _gain_loss_matrix;
+
+ private DolloParsimony() {
+ init();
+ }
+
+ public void execute( final Phylogeny p, final CharacterStateMatrix<BinaryStates> external_node_states_matrix ) {
+ if ( !p.isRooted() ) {
+ throw new IllegalArgumentException( "attempt to execute Dollo parsimony on unroored phylogeny" );
+ }
+ if ( external_node_states_matrix.isEmpty() ) {
+ throw new IllegalArgumentException( "character matrix is empty" );
+ }
+ if ( external_node_states_matrix.getNumberOfIdentifiers() != p.getNumberOfExternalNodes() ) {
+ throw new IllegalArgumentException( "number of external nodes in phylogeny ["
+ + p.getNumberOfExternalNodes() + "] and number of indentifiers ["
+ + external_node_states_matrix.getNumberOfIdentifiers() + "] in matrix are not equal" );
+ }
+ reset();
+ if ( isReturnInternalStates() ) {
+ initializeInternalStates( p, external_node_states_matrix );
+ }
+ if ( isReturnGainLossMatrix() ) {
+ initializeGainLossMatrix( p, external_node_states_matrix );
+ }
+ for( int character_index = 0; character_index < external_node_states_matrix.getNumberOfCharacters(); ++character_index ) {
+ executeForOneCharacter( p,
+ getStatesForCharacter( p, external_node_states_matrix, character_index ),
+ character_index );
+ }
+ if ( ( external_node_states_matrix.getNumberOfCharacters() * p.getNumberOfBranches() ) != ( getTotalGains()
+ + getTotalLosses() + getTotalUnchanged() ) ) {
+ throw new AssertionError( "this should not have happened: something is deeply wrong with Dollo parsimony implementation" );
+ }
+ }
+
+ private void executeForOneCharacter( final Phylogeny p,
+ final Map<PhylogenyNode, BinaryStates> states,
+ final int character_state_column ) {
+ postOrderTraversal( p, states );
+ preOrderTraversal( p, states, character_state_column );
+ }
+
+ /* (non-Javadoc)
+ * @see org.forester.phylogenyinference.Parsimony#getCost()
+ */
+ public int getCost() {
+ return getTotalGains() + getTotalLosses();
+ }
+
+ /* (non-Javadoc)
+ * @see org.forester.phylogenyinference.Parsimony#getGainLossMatrix()
+ */
+ public CharacterStateMatrix<CharacterStateMatrix.GainLossStates> getGainLossMatrix() {
+ if ( !isReturnGainLossMatrix() ) {
+ throw new RuntimeException( "creation of gain-loss matrix has not been enabled" );
+ }
+ return _gain_loss_matrix;
+ }
+
+ /* (non-Javadoc)
+ * @see org.forester.phylogenyinference.Parsimony#getInternalStatesMatrix()
+ */
+ public CharacterStateMatrix<BinaryStates> getInternalStatesMatrix() {
+ if ( !isReturnInternalStates() ) {
+ throw new RuntimeException( "creation of internal state matrix has not been enabled" );
+ }
+ return _internal_states_matrix;
+ }
+
+ private Map<PhylogenyNode, BinaryStates> getStatesForCharacter( final Phylogeny p,
+ final CharacterStateMatrix<BinaryStates> matrix,
+ final int character_index ) {
+ final Map<PhylogenyNode, BinaryStates> states = new HashMap<PhylogenyNode, BinaryStates>( matrix
+ .getNumberOfIdentifiers() );
+ for( int indentifier_index = 0; indentifier_index < matrix.getNumberOfIdentifiers(); ++indentifier_index ) {
+ final BinaryStates state = matrix.getState( indentifier_index, character_index );
+ if ( state == null ) {
+ throw new IllegalArgumentException( "value at [" + indentifier_index + ", " + character_index
+ + "] is null" );
+ }
+ states.put( p.getNode( matrix.getIdentifier( indentifier_index ) ), state );
+ }
+ return states;
+ }
+
+ /* (non-Javadoc)
+ * @see org.forester.phylogenyinference.Parsimony#getTotalGains()
+ */
+ public int getTotalGains() {
+ return _total_gains;
+ }
+
+ /* (non-Javadoc)
+ * @see org.forester.phylogenyinference.Parsimony#getTotalLosses()
+ */
+ public int getTotalLosses() {
+ return _total_losses;
+ }
+
+ /* (non-Javadoc)
+ * @see org.forester.phylogenyinference.Parsimony#getTotalUnchanged()
+ */
+ public int getTotalUnchanged() {
+ return _total_unchanged;
+ }
+
+ private void init() {
+ setReturnInternalStates( RETURN_INTERNAL_STATES_DEFAULT );
+ setReturnGainLossMatrix( RETURN_GAIN_LOSS_MATRIX_DEFAULT );
+ reset();
+ }
+
+ private void initializeGainLossMatrix( final Phylogeny p,
+ final CharacterStateMatrix<BinaryStates> external_node_states_matrix ) {
+ final List<PhylogenyNode> nodes = new ArrayList<PhylogenyNode>();
+ for( final PhylogenyNodeIterator postorder = p.iteratorPostorder(); postorder.hasNext(); ) {
+ nodes.add( postorder.next() );
+ }
+ setGainLossMatrix( new BasicCharacterStateMatrix<CharacterStateMatrix.GainLossStates>( nodes.size(),
+ external_node_states_matrix
+ .getNumberOfCharacters() ) );
+ int identifier_index = 0;
+ for( final PhylogenyNode node : nodes ) {
+ getGainLossMatrix().setIdentifier( identifier_index++,
+ ForesterUtil.isEmpty( node.getName() ) ? node.getId() + "" : node
+ .getName() );
+ }
+ for( int character_index = 0; character_index < external_node_states_matrix.getNumberOfCharacters(); ++character_index ) {
+ getGainLossMatrix().setCharacter( character_index,
+ external_node_states_matrix.getCharacter( character_index ) );
+ }
+ }
+
+ private void initializeInternalStates( final Phylogeny p,
+ final CharacterStateMatrix<BinaryStates> external_node_states_matrix ) {
+ final List<PhylogenyNode> internal_nodes = new ArrayList<PhylogenyNode>();
+ for( final PhylogenyNodeIterator postorder = p.iteratorPostorder(); postorder.hasNext(); ) {
+ final PhylogenyNode node = postorder.next();
+ if ( node.isInternal() ) {
+ internal_nodes.add( node );
+ }
+ }
+ setInternalStatesMatrix( new BasicCharacterStateMatrix<BinaryStates>( internal_nodes.size(),
+ external_node_states_matrix
+ .getNumberOfCharacters() ) );
+ int identifier_index = 0;
+ for( final PhylogenyNode node : internal_nodes ) {
+ getInternalStatesMatrix().setIdentifier( identifier_index++,
+ ForesterUtil.isEmpty( node.getName() ) ? node.getId() + "" : node
+ .getName() );
+ }
+ for( int character_index = 0; character_index < external_node_states_matrix.getNumberOfCharacters(); ++character_index ) {
+ getInternalStatesMatrix().setCharacter( character_index,
+ external_node_states_matrix.getCharacter( character_index ) );
+ }
+ }
+
+ private boolean isReturnGainLossMatrix() {
+ return _return_gain_loss;
+ }
+
+ private boolean isReturnInternalStates() {
+ return _return_internal_states;
+ }
+
+ private void postOrderTraversal( final Phylogeny p, final Map<PhylogenyNode, BinaryStates> states )
+ throws AssertionError {
+ for( final PhylogenyNodeIterator postorder = p.iteratorPostorder(); postorder.hasNext(); ) {
+ final PhylogenyNode node = postorder.next();
+ if ( !node.isExternal() ) {
+ final int present_unknown = getNumberOfChildNodesWithPresentOrUnknownState( states, node );
+ if ( present_unknown < 1 ) {
+ states.put( node, ABSENT );
+ }
+ else if ( present_unknown == 1 ) {
+ states.put( node, UNKNOWN );
+ }
+ else {
+ states.put( node, PRESENT );
+ }
+ }
+ }
+ }
+
+ private void preOrderTraversal( final Phylogeny p,
+ final Map<PhylogenyNode, BinaryStates> states,
+ final int character_state_column ) throws AssertionError {
+ boolean gain = false;
+ for( final PhylogenyNodeIterator preorder = p.iteratorPreorder(); preorder.hasNext(); ) {
+ final PhylogenyNode node = preorder.next();
+ BinaryStates parent_state = null;
+ if ( !node.isRoot() ) {
+ parent_state = states.get( node.getParent() );
+ }
+ if ( !node.isExternal() ) {
+ if ( states.get( node ) == UNKNOWN ) {
+ if ( parent_state == PRESENT ) {
+ states.put( node, PRESENT );
+ }
+ else {
+ if ( isCharacterPresentOrUnknownInAtLeastTwoChildNodes( states, node ) ) {
+ states.put( node, PRESENT );
+ }
+ else {
+ states.put( node, ABSENT );
+ }
+ }
+ }
+ if ( isReturnInternalStates() ) {
+ setInternalNodeState( states, character_state_column, node );
+ }
+ }
+ final BinaryStates current_state = states.get( node );
+ if ( ( parent_state == PRESENT ) && ( current_state == ABSENT ) ) {
+ ++_total_losses;
+ if ( isReturnGainLossMatrix() ) {
+ setGainLossState( character_state_column, node, LOSS );
+ }
+ }
+ else if ( ( ( parent_state == ABSENT ) ) && ( current_state == PRESENT ) ) {
+ if ( gain ) {
+ throw new RuntimeException( "this should not have happened: dollo parsimony cannot have more than one gain" );
+ }
+ gain = true;
+ ++_total_gains;
+ if ( isReturnGainLossMatrix() ) {
+ setGainLossState( character_state_column, node, GAIN );
+ }
+ }
+ else {
+ ++_total_unchanged;
+ if ( isReturnGainLossMatrix() ) {
+ if ( current_state == PRESENT ) {
+ setGainLossState( character_state_column, node, UNCHANGED_PRESENT );
+ }
+ else if ( current_state == ABSENT ) {
+ setGainLossState( character_state_column, node, UNCHANGED_ABSENT );
+ }
+ }
+ }
+ }
+ }
+
+ private void reset() {
+ setTotalLosses( 0 );
+ setTotalGains( 0 );
+ setTotalUnchanged( 0 );
+ }
+
+ private void setGainLossMatrix( final CharacterStateMatrix<CharacterStateMatrix.GainLossStates> gain_loss_matrix ) {
+ _gain_loss_matrix = gain_loss_matrix;
+ }
+
+ private void setGainLossState( final int character_state_column,
+ final PhylogenyNode node,
+ final GainLossStates state ) {
+ getGainLossMatrix().setState( ForesterUtil.isEmpty( node.getName() ) ? node.getId() + "" : node.getName(),
+ character_state_column,
+ state );
+ }
+
+ private void setInternalNodeState( final Map<PhylogenyNode, BinaryStates> states,
+ final int character_state_column,
+ final PhylogenyNode node ) {
+ getInternalStatesMatrix()
+ .setState( ForesterUtil.isEmpty( node.getName() ) ? node.getId() + "" : node.getName(),
+ character_state_column,
+ states.get( node ) );
+ }
+
+ private void setInternalStatesMatrix( final CharacterStateMatrix<BinaryStates> internal_states_matrix ) {
+ _internal_states_matrix = internal_states_matrix;
+ }
+
+ /* (non-Javadoc)
+ * @see org.forester.phylogenyinference.Parsimony#setReturnGainLossMatrix(boolean)
+ */
+ public void setReturnGainLossMatrix( final boolean return_gain_loss ) {
+ _return_gain_loss = return_gain_loss;
+ }
+
+ /* (non-Javadoc)
+ * @see org.forester.phylogenyinference.Parsimony#setReturnInternalStates(boolean)
+ */
+ public void setReturnInternalStates( final boolean return_internal_states ) {
+ _return_internal_states = return_internal_states;
+ }
+
+ private void setTotalGains( final int total_gains ) {
+ _total_gains = total_gains;
+ }
+
+ private void setTotalLosses( final int total_losses ) {
+ _total_losses = total_losses;
+ }
+
+ private void setTotalUnchanged( final int total_unchanged ) {
+ _total_unchanged = total_unchanged;
+ }
+
+ public static DolloParsimony createInstance() {
+ return new DolloParsimony();
+ }
+
+ private static int getNumberOfChildNodesWithPresentOrUnknownState( final Map<PhylogenyNode, BinaryStates> states,
+ final PhylogenyNode node ) {
+ int presents = 0;
+ for( int i = 0; i < node.getNumberOfDescendants(); ++i ) {
+ final PhylogenyNode node_child = node.getChildNode( i );
+ if ( !states.containsKey( node_child ) ) {
+ throw new RuntimeException( "this should not have happened: node [" + node_child.getName()
+ + "] not found in node state map" );
+ }
+ if ( ( states.get( node_child ) == BinaryStates.PRESENT )
+ || ( states.get( node_child ) == BinaryStates.UNKNOWN ) ) {
+ ++presents;
+ }
+ }
+ return presents;
+ }
+
+ private static boolean isCharacterPresentOrUnknownInAtLeastTwoChildNodes( final Map<PhylogenyNode, BinaryStates> states,
+ final PhylogenyNode node ) {
+ int count = 0;
+ for( int i = 0; i < node.getNumberOfDescendants(); ++i ) {
+ final PhylogenyNode node_child = node.getChildNode( i );
+ if ( ( states.get( node_child ) == PRESENT ) || ( states.get( node_child ) == UNKNOWN ) ) {
+ ++count;
+ if ( count > 1 ) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+}
--- /dev/null
+// $Id:
+//
+// FORESTER -- software libraries and applications
+// for evolutionary biology research and applications.
+//
+// Copyright (C) 2008-2009 Christian M. Zmasek
+// Copyright (C) 2008-2009 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: www.phylosoft.org/forester
+
+package org.forester.evoinference.parsimony;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+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.evoinference.matrix.character.CharacterStateMatrix.GainLossStates;
+import org.forester.phylogeny.Phylogeny;
+import org.forester.phylogeny.PhylogenyNode;
+import org.forester.phylogeny.iterators.PhylogenyNodeIterator;
+import org.forester.util.FailedConditionCheckException;
+import org.forester.util.ForesterUtil;
+
+public class FitchParsimony<STATE_TYPE> {
+
+ final static private BinaryStates PRESENT = BinaryStates.PRESENT;
+ final static private BinaryStates ABSENT = BinaryStates.ABSENT;
+ final static private GainLossStates LOSS = GainLossStates.LOSS;
+ final static private GainLossStates GAIN = GainLossStates.GAIN;
+ final static private GainLossStates UNCHANGED_PRESENT = GainLossStates.UNCHANGED_PRESENT;
+ final static private GainLossStates UNCHANGED_ABSENT = GainLossStates.UNCHANGED_ABSENT;
+ private static final boolean RETURN_INTERNAL_STATES_DEFAULT = false;
+ private static final boolean RETURN_GAIN_LOSS_MATRIX_DEFAULT = false;
+ private static final boolean RANDOMIZE_DEFAULT = false;
+ private static final long RANDOM_NUMBER_SEED_DEFAULT = 21;
+ private static final boolean USE_LAST_DEFAULT = false;
+ private boolean _return_internal_states = false;
+ private boolean _return_gain_loss = false;
+ private int _total_gains;
+ private int _total_losses;
+ private int _total_unchanged;
+ private CharacterStateMatrix<List<STATE_TYPE>> _internal_states_matrix_prior_to_traceback;
+ private CharacterStateMatrix<STATE_TYPE> _internal_states_matrix_after_traceback;
+ private CharacterStateMatrix<GainLossStates> _gain_loss_matrix;
+ private boolean _randomize;
+ private boolean _use_last;
+ private int _cost;
+ private long _random_number_seed;
+ private Random _random_generator;
+
+ public FitchParsimony() {
+ init();
+ }
+
+ private int determineIndex( final SortedSet<STATE_TYPE> current_node_states, int i ) {
+ if ( isRandomize() ) {
+ i = getRandomGenerator().nextInt( current_node_states.size() );
+ }
+ else if ( isUseLast() ) {
+ i = current_node_states.size() - 1;
+ }
+ return i;
+ }
+
+ public void execute( final Phylogeny p, final CharacterStateMatrix<STATE_TYPE> external_node_states_matrix ) {
+ if ( !p.isRooted() ) {
+ throw new IllegalArgumentException( "attempt to execute Fitch parsimony on unroored phylogeny" );
+ }
+ if ( external_node_states_matrix.isEmpty() ) {
+ throw new IllegalArgumentException( "character matrix is empty" );
+ }
+ if ( external_node_states_matrix.getNumberOfIdentifiers() != p.getNumberOfExternalNodes() ) {
+ throw new IllegalArgumentException( "number of external nodes in phylogeny ["
+ + p.getNumberOfExternalNodes() + "] and number of indentifiers ["
+ + external_node_states_matrix.getNumberOfIdentifiers() + "] in matrix are not equal" );
+ }
+ reset();
+ if ( isReturnInternalStates() ) {
+ initializeInternalStates( p, external_node_states_matrix );
+ }
+ if ( isReturnGainLossMatrix() ) {
+ initializeGainLossMatrix( p, external_node_states_matrix );
+ }
+ for( int character_index = 0; character_index < external_node_states_matrix.getNumberOfCharacters(); ++character_index ) {
+ executeForOneCharacter( p,
+ getStatesForCharacter( p, external_node_states_matrix, character_index ),
+ getStatesForCharacterForTraceback( p, external_node_states_matrix, character_index ),
+ character_index );
+ }
+ if ( external_node_states_matrix.getState( 0, 0 ) instanceof BinaryStates ) {
+ if ( ( external_node_states_matrix.getNumberOfCharacters() * p.getNumberOfBranches() ) != ( getTotalGains()
+ + getTotalLosses() + getTotalUnchanged() ) ) {
+ throw new FailedConditionCheckException( "this should not have happened: something is deeply wrong with Fitch parsimony implementation" );
+ }
+ }
+ }
+
+ private void executeForOneCharacter( final Phylogeny p,
+ final Map<PhylogenyNode, SortedSet<STATE_TYPE>> states,
+ final Map<PhylogenyNode, STATE_TYPE> traceback_states,
+ final int character_state_column ) {
+ postOrderTraversal( p, states );
+ preOrderTraversal( p, states, traceback_states, character_state_column );
+ }
+
+ public int getCost() {
+ return _cost;
+ }
+
+ public CharacterStateMatrix<CharacterStateMatrix.GainLossStates> getGainLossMatrix() {
+ if ( !isReturnGainLossMatrix() ) {
+ throw new RuntimeException( "creation of gain-loss matrix has not been enabled" );
+ }
+ return _gain_loss_matrix;
+ }
+
+ public CharacterStateMatrix<STATE_TYPE> getInternalStatesMatrix() {
+ if ( !isReturnInternalStates() ) {
+ throw new RuntimeException( "creation of internal state matrix has not been enabled" );
+ }
+ return _internal_states_matrix_after_traceback;
+ }
+
+ /**
+ * Returns a view of the internal states prior to trace-back.
+ *
+ * @return
+ */
+ public CharacterStateMatrix<List<STATE_TYPE>> getInternalStatesMatrixPriorToTraceback() {
+ if ( !isReturnInternalStates() ) {
+ throw new RuntimeException( "creation of internal state matrix has not been enabled" );
+ }
+ return _internal_states_matrix_prior_to_traceback;
+ }
+
+ private SortedSet<STATE_TYPE> getIntersectionOfStatesOfChildNodes( final Map<PhylogenyNode, SortedSet<STATE_TYPE>> states,
+ final PhylogenyNode node ) throws AssertionError {
+ final SortedSet<STATE_TYPE> states_in_child_nodes = new TreeSet<STATE_TYPE>();
+ for( int i = 0; i < node.getNumberOfDescendants(); ++i ) {
+ final PhylogenyNode node_child = node.getChildNode( i );
+ if ( !states.containsKey( node_child ) ) {
+ throw new AssertionError( "this should not have happened: node [" + node_child.getName()
+ + "] not found in node state map" );
+ }
+ if ( i == 0 ) {
+ states_in_child_nodes.addAll( states.get( node_child ) );
+ }
+ else {
+ states_in_child_nodes.retainAll( states.get( node_child ) );
+ }
+ }
+ return states_in_child_nodes;
+ }
+
+ private Random getRandomGenerator() {
+ return _random_generator;
+ }
+
+ private long getRandomNumberSeed() {
+ return _random_number_seed;
+ }
+
+ private STATE_TYPE getStateAt( final int i, final SortedSet<STATE_TYPE> states ) {
+ final Iterator<STATE_TYPE> it = states.iterator();
+ for( int j = 0; j < i; ++j ) {
+ it.next();
+ }
+ return it.next();
+ }
+
+ private Map<PhylogenyNode, SortedSet<STATE_TYPE>> getStatesForCharacter( final Phylogeny p,
+ final CharacterStateMatrix<STATE_TYPE> matrix,
+ final int character_index ) {
+ final Map<PhylogenyNode, SortedSet<STATE_TYPE>> states = new HashMap<PhylogenyNode, SortedSet<STATE_TYPE>>( matrix
+ .getNumberOfIdentifiers() );
+ for( int indentifier_index = 0; indentifier_index < matrix.getNumberOfIdentifiers(); ++indentifier_index ) {
+ final STATE_TYPE state = matrix.getState( indentifier_index, character_index );
+ if ( state == null ) {
+ throw new IllegalArgumentException( "value at [" + indentifier_index + ", " + character_index
+ + "] is null" );
+ }
+ final SortedSet<STATE_TYPE> l = new TreeSet<STATE_TYPE>();
+ l.add( state );
+ states.put( p.getNode( matrix.getIdentifier( indentifier_index ) ), l );
+ }
+ return states;
+ }
+
+ private Map<PhylogenyNode, STATE_TYPE> getStatesForCharacterForTraceback( final Phylogeny p,
+ final CharacterStateMatrix<STATE_TYPE> matrix,
+ final int character_index ) {
+ final Map<PhylogenyNode, STATE_TYPE> states = new HashMap<PhylogenyNode, STATE_TYPE>( matrix
+ .getNumberOfIdentifiers() );
+ for( int indentifier_index = 0; indentifier_index < matrix.getNumberOfIdentifiers(); ++indentifier_index ) {
+ final STATE_TYPE state = matrix.getState( indentifier_index, character_index );
+ if ( state == null ) {
+ throw new IllegalArgumentException( "value at [" + indentifier_index + ", " + character_index
+ + "] is null" );
+ }
+ states.put( p.getNode( matrix.getIdentifier( indentifier_index ) ), state );
+ }
+ return states;
+ }
+
+ public int getTotalGains() {
+ return _total_gains;
+ }
+
+ public int getTotalLosses() {
+ return _total_losses;
+ }
+
+ public int getTotalUnchanged() {
+ return _total_unchanged;
+ }
+
+ private SortedSet<STATE_TYPE> getUnionOfStatesOfChildNodes( final Map<PhylogenyNode, SortedSet<STATE_TYPE>> states,
+ final PhylogenyNode node ) throws AssertionError {
+ final SortedSet<STATE_TYPE> states_in_child_nodes = new TreeSet<STATE_TYPE>();
+ for( int i = 0; i < node.getNumberOfDescendants(); ++i ) {
+ final PhylogenyNode node_child = node.getChildNode( i );
+ if ( !states.containsKey( node_child ) ) {
+ throw new AssertionError( "this should not have happened: node [" + node_child.getName()
+ + "] not found in node state map" );
+ }
+ states_in_child_nodes.addAll( states.get( node_child ) );
+ }
+ return states_in_child_nodes;
+ }
+
+ private void increaseCost() {
+ ++_cost;
+ }
+
+ private void init() {
+ setReturnInternalStates( RETURN_INTERNAL_STATES_DEFAULT );
+ setReturnGainLossMatrix( RETURN_GAIN_LOSS_MATRIX_DEFAULT );
+ setRandomize( RANDOMIZE_DEFAULT );
+ setUseLast( USE_LAST_DEFAULT );
+ _random_number_seed = RANDOM_NUMBER_SEED_DEFAULT;
+ reset();
+ }
+
+ private void initializeGainLossMatrix( final Phylogeny p,
+ final CharacterStateMatrix<STATE_TYPE> external_node_states_matrix ) {
+ final List<PhylogenyNode> nodes = new ArrayList<PhylogenyNode>();
+ for( final PhylogenyNodeIterator postorder = p.iteratorPostorder(); postorder.hasNext(); ) {
+ nodes.add( postorder.next() );
+ }
+ setGainLossMatrix( new BasicCharacterStateMatrix<CharacterStateMatrix.GainLossStates>( nodes.size(),
+ external_node_states_matrix
+ .getNumberOfCharacters() ) );
+ int identifier_index = 0;
+ for( final PhylogenyNode node : nodes ) {
+ getGainLossMatrix().setIdentifier( identifier_index++,
+ ForesterUtil.isEmpty( node.getName() ) ? node.getId() + "" : node
+ .getName() );
+ }
+ for( int character_index = 0; character_index < external_node_states_matrix.getNumberOfCharacters(); ++character_index ) {
+ getGainLossMatrix().setCharacter( character_index,
+ external_node_states_matrix.getCharacter( character_index ) );
+ }
+ }
+
+ private void initializeInternalStates( final Phylogeny p,
+ final CharacterStateMatrix<STATE_TYPE> external_node_states_matrix ) {
+ final List<PhylogenyNode> internal_nodes = new ArrayList<PhylogenyNode>();
+ for( final PhylogenyNodeIterator postorder = p.iteratorPostorder(); postorder.hasNext(); ) {
+ final PhylogenyNode node = postorder.next();
+ if ( node.isInternal() ) {
+ internal_nodes.add( node );
+ }
+ }
+ setInternalStatesMatrixPriorToTraceback( new BasicCharacterStateMatrix<List<STATE_TYPE>>( internal_nodes.size(),
+ external_node_states_matrix
+ .getNumberOfCharacters() ) );
+ setInternalStatesMatrixTraceback( new BasicCharacterStateMatrix<STATE_TYPE>( internal_nodes.size(),
+ external_node_states_matrix
+ .getNumberOfCharacters() ) );
+ int identifier_index = 0;
+ for( final PhylogenyNode node : internal_nodes ) {
+ getInternalStatesMatrix().setIdentifier( identifier_index,
+ ForesterUtil.isEmpty( node.getName() ) ? node.getId() + "" : node
+ .getName() );
+ getInternalStatesMatrixPriorToTraceback().setIdentifier( identifier_index,
+ ForesterUtil.isEmpty( node.getName() ) ? node
+ .getId()
+ + "" : node.getName() );
+ ++identifier_index;
+ }
+ for( int character_index = 0; character_index < external_node_states_matrix.getNumberOfCharacters(); ++character_index ) {
+ getInternalStatesMatrix().setCharacter( character_index,
+ external_node_states_matrix.getCharacter( character_index ) );
+ getInternalStatesMatrixPriorToTraceback().setCharacter( character_index,
+ external_node_states_matrix
+ .getCharacter( character_index ) );
+ }
+ }
+
+ private boolean isRandomize() {
+ return _randomize;
+ }
+
+ private boolean isReturnGainLossMatrix() {
+ return _return_gain_loss;
+ }
+
+ private boolean isReturnInternalStates() {
+ return _return_internal_states;
+ }
+
+ private boolean isUseLast() {
+ return _use_last;
+ }
+
+ private void postOrderTraversal( final Phylogeny p, final Map<PhylogenyNode, SortedSet<STATE_TYPE>> states )
+ throws AssertionError {
+ for( final PhylogenyNodeIterator postorder = p.iteratorPostorder(); postorder.hasNext(); ) {
+ final PhylogenyNode node = postorder.next();
+ if ( !node.isExternal() ) {
+ SortedSet<STATE_TYPE> states_in_children = getIntersectionOfStatesOfChildNodes( states, node );
+ if ( states_in_children.isEmpty() ) {
+ states_in_children = getUnionOfStatesOfChildNodes( states, node );
+ }
+ states.put( node, states_in_children );
+ }
+ }
+ }
+
+ private void preOrderTraversal( final Phylogeny p,
+ final Map<PhylogenyNode, SortedSet<STATE_TYPE>> states,
+ final Map<PhylogenyNode, STATE_TYPE> traceback_states,
+ final int character_state_column ) throws AssertionError {
+ for( final PhylogenyNodeIterator preorder = p.iteratorPreorder(); preorder.hasNext(); ) {
+ final PhylogenyNode current_node = preorder.next();
+ final SortedSet<STATE_TYPE> current_node_states = states.get( current_node );
+ STATE_TYPE parent_state = null;
+ if ( current_node.isRoot() ) {
+ int i = 0;
+ i = determineIndex( current_node_states, i );
+ traceback_states.put( current_node, getStateAt( i, current_node_states ) );
+ }
+ else {
+ parent_state = traceback_states.get( current_node.getParent() );
+ if ( current_node_states.contains( parent_state ) ) {
+ traceback_states.put( current_node, parent_state );
+ }
+ else {
+ increaseCost();
+ int i = 0;
+ i = determineIndex( current_node_states, i );
+ traceback_states.put( current_node, getStateAt( i, current_node_states ) );
+ }
+ }
+ if ( isReturnInternalStates() ) {
+ if ( !current_node.isExternal() ) {
+ setInternalNodeStatePriorToTraceback( states, character_state_column, current_node );
+ setInternalNodeState( traceback_states, character_state_column, current_node );
+ }
+ }
+ if ( isReturnGainLossMatrix() && !current_node.isRoot() ) {
+ if ( !( parent_state instanceof BinaryStates ) ) {
+ throw new RuntimeException( "attempt to create gain loss matrix for not binary states" );
+ }
+ final BinaryStates parent_binary_state = ( BinaryStates ) parent_state;
+ final BinaryStates current_binary_state = ( BinaryStates ) traceback_states.get( current_node );
+ if ( ( parent_binary_state == PRESENT ) && ( current_binary_state == ABSENT ) ) {
+ ++_total_losses;
+ setGainLossState( character_state_column, current_node, LOSS );
+ }
+ else if ( ( ( parent_binary_state == ABSENT ) || ( parent_binary_state == null ) )
+ && ( current_binary_state == PRESENT ) ) {
+ ++_total_gains;
+ setGainLossState( character_state_column, current_node, GAIN );
+ }
+ else {
+ ++_total_unchanged;
+ if ( current_binary_state == PRESENT ) {
+ setGainLossState( character_state_column, current_node, UNCHANGED_PRESENT );
+ }
+ else if ( current_binary_state == ABSENT ) {
+ setGainLossState( character_state_column, current_node, UNCHANGED_ABSENT );
+ }
+ }
+ }
+ else if ( isReturnGainLossMatrix() && current_node.isRoot() ) {
+ final BinaryStates current_binary_state = ( BinaryStates ) traceback_states.get( current_node );
+ ++_total_unchanged; //new
+ if ( current_binary_state == PRESENT ) {//new
+ setGainLossState( character_state_column, current_node, UNCHANGED_PRESENT );//new
+ }//new
+ else if ( current_binary_state == ABSENT ) {//new
+ setGainLossState( character_state_column, current_node, UNCHANGED_ABSENT );//new
+ }//new
+ // setGainLossState( character_state_column, current_node, UNKNOWN_GAIN_LOSS );
+ }
+ }
+ }
+
+ private void reset() {
+ setCost( 0 );
+ setTotalLosses( 0 );
+ setTotalGains( 0 );
+ setTotalUnchanged( 0 );
+ setRandomGenerator( new Random( getRandomNumberSeed() ) );
+ }
+
+ private void setCost( final int cost ) {
+ _cost = cost;
+ }
+
+ private void setGainLossMatrix( final CharacterStateMatrix<GainLossStates> gain_loss_matrix ) {
+ _gain_loss_matrix = gain_loss_matrix;
+ }
+
+ private void setGainLossState( final int character_state_column,
+ final PhylogenyNode node,
+ final GainLossStates state ) {
+ getGainLossMatrix().setState( ForesterUtil.isEmpty( node.getName() ) ? node.getId() + "" : node.getName(),
+ character_state_column,
+ state );
+ }
+
+ private void setInternalNodeState( final Map<PhylogenyNode, STATE_TYPE> states,
+ final int character_state_column,
+ final PhylogenyNode node ) {
+ getInternalStatesMatrix()
+ .setState( ForesterUtil.isEmpty( node.getName() ) ? node.getId() + "" : node.getName(),
+ character_state_column,
+ states.get( node ) );
+ }
+
+ private void setInternalNodeStatePriorToTraceback( final Map<PhylogenyNode, SortedSet<STATE_TYPE>> states,
+ final int character_state_column,
+ final PhylogenyNode node ) {
+ getInternalStatesMatrixPriorToTraceback().setState( ForesterUtil.isEmpty( node.getName() ) ? node.getId() + ""
+ : node.getName(),
+ character_state_column,
+ toListSorted( states.get( node ) ) );
+ }
+
+ private void setInternalStatesMatrixPriorToTraceback( final CharacterStateMatrix<List<STATE_TYPE>> internal_states_matrix_prior_to_traceback ) {
+ _internal_states_matrix_prior_to_traceback = internal_states_matrix_prior_to_traceback;
+ }
+
+ private void setInternalStatesMatrixTraceback( final CharacterStateMatrix<STATE_TYPE> internal_states_matrix_after_traceback ) {
+ _internal_states_matrix_after_traceback = internal_states_matrix_after_traceback;
+ }
+
+ private void setRandomGenerator( final Random random_generator ) {
+ _random_generator = random_generator;
+ }
+
+ public void setRandomize( final boolean randomize ) {
+ if ( randomize && isUseLast() ) {
+ throw new IllegalArgumentException( "attempt to allways use last state (ordered) if more than one choices and randomization at the same time" );
+ }
+ _randomize = randomize;
+ }
+
+ public void setRandomNumberSeed( final long random_number_seed ) {
+ if ( !isRandomize() ) {
+ throw new IllegalArgumentException( "attempt to set random number generator seed without randomization enabled" );
+ }
+ _random_number_seed = random_number_seed;
+ }
+
+ public void setReturnGainLossMatrix( final boolean return_gain_loss ) {
+ _return_gain_loss = return_gain_loss;
+ }
+
+ public void setReturnInternalStates( final boolean return_internal_states ) {
+ _return_internal_states = return_internal_states;
+ }
+
+ private void setTotalGains( final int total_gains ) {
+ _total_gains = total_gains;
+ }
+
+ private void setTotalLosses( final int total_losses ) {
+ _total_losses = total_losses;
+ }
+
+ private void setTotalUnchanged( final int total_unchanged ) {
+ _total_unchanged = total_unchanged;
+ }
+
+ /**
+ * This sets whether to use the first or last state in the sorted
+ * states at the undecided internal nodes.
+ * For randomized choices set randomize to true (and this to false).
+ *
+ * Note. It might be advisable to set this to false
+ * for BinaryStates if absence at the root is preferred
+ * (given the enum BinaryStates sorts in the following order:
+ * ABSENT, UNKNOWN, PRESENT).
+ *
+ *
+ * @param use_last
+ */
+ public void setUseLast( final boolean use_last ) {
+ if ( use_last && isRandomize() ) {
+ throw new IllegalArgumentException( "attempt to allways use last state (ordered) if more than one choices and randomization at the same time" );
+ }
+ _use_last = use_last;
+ }
+
+ private List<STATE_TYPE> toListSorted( final SortedSet<STATE_TYPE> states ) {
+ final List<STATE_TYPE> l = new ArrayList<STATE_TYPE>( states.size() );
+ for( final STATE_TYPE state : states ) {
+ l.add( state );
+ }
+ return l;
+ }
+}
--- /dev/null
+// $Id:
+//
+// FORESTER -- software libraries and applications
+// for evolutionary biology research and applications.
+//
+// Copyright (C) 2008-2009 Christian M. Zmasek
+// Copyright (C) 2008-2009 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: www.phylosoft.org
+
+package org.forester.evoinference.parsimony;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+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.evoinference.matrix.character.CharacterStateMatrix.GainLossStates;
+import org.forester.phylogeny.Phylogeny;
+import org.forester.phylogeny.PhylogenyNode;
+import org.forester.phylogeny.iterators.PhylogenyNodeIterator;
+import org.forester.util.ForesterUtil;
+
+/**
+ *
+ * IN PROGRESS!
+ * DO NOT USE!
+ *
+ *
+ * @param <STATE_TYPE>
+ */
+public class SankoffParsimony<STATE_TYPE> {
+
+ final static private BinaryStates PRESENT = BinaryStates.PRESENT;
+ final static private BinaryStates ABSENT = BinaryStates.ABSENT;
+ final static private GainLossStates LOSS = GainLossStates.LOSS;
+ final static private GainLossStates GAIN = GainLossStates.GAIN;
+ final static private GainLossStates UNCHANGED_PRESENT = GainLossStates.UNCHANGED_PRESENT;
+ final static private GainLossStates UNCHANGED_ABSENT = GainLossStates.UNCHANGED_ABSENT;
+ private static final boolean RETURN_INTERNAL_STATES_DEFAULT = false;
+ private static final boolean RETURN_GAIN_LOSS_MATRIX_DEFAULT = false;
+ private static final boolean RANDOMIZE_DEFAULT = false;
+ private static final long RANDOM_NUMBER_SEED_DEFAULT = 21;
+ private static final boolean USE_LAST_DEFAULT = false;
+ private boolean _return_internal_states = false;
+ private boolean _return_gain_loss = false;
+ private int _total_gains;
+ private int _total_losses;
+ private int _total_unchanged;
+ private CharacterStateMatrix<List<STATE_TYPE>> _internal_states_matrix_prior_to_traceback;
+ private CharacterStateMatrix<STATE_TYPE> _internal_states_matrix_after_traceback;
+ private CharacterStateMatrix<GainLossStates> _gain_loss_matrix;
+ private boolean _randomize;
+ private boolean _use_last;
+ private int _cost;
+ private long _random_number_seed;
+ private Random _random_generator;
+
+ public SankoffParsimony() {
+ init();
+ }
+
+ private int determineIndex( final SortedSet<STATE_TYPE> current_node_states, int i ) {
+ if ( isRandomize() ) {
+ i = getRandomGenerator().nextInt( current_node_states.size() );
+ }
+ else if ( isUseLast() ) {
+ i = current_node_states.size() - 1;
+ }
+ return i;
+ }
+
+ public void execute( final Phylogeny p, final CharacterStateMatrix<STATE_TYPE> external_node_states_matrix ) {
+ if ( !p.isRooted() ) {
+ throw new IllegalArgumentException( "attempt to execute Fitch parsimony on unroored phylogeny" );
+ }
+ if ( external_node_states_matrix.isEmpty() ) {
+ throw new IllegalArgumentException( "character matrix is empty" );
+ }
+ if ( external_node_states_matrix.getNumberOfIdentifiers() != p.getNumberOfExternalNodes() ) {
+ throw new IllegalArgumentException( "number of external nodes in phylogeny ["
+ + p.getNumberOfExternalNodes() + "] and number of indentifiers ["
+ + external_node_states_matrix.getNumberOfIdentifiers() + "] in matrix are not equal" );
+ }
+ reset();
+ if ( isReturnInternalStates() ) {
+ initializeInternalStates( p, external_node_states_matrix );
+ }
+ if ( isReturnGainLossMatrix() ) {
+ initializeGainLossMatrix( p, external_node_states_matrix );
+ }
+ for( int character_index = 0; character_index < external_node_states_matrix.getNumberOfCharacters(); ++character_index ) {
+ executeForOneCharacter( p,
+ getStatesForCharacter( p, external_node_states_matrix, character_index ),
+ getStatesForCharacterForTraceback( p, external_node_states_matrix, character_index ),
+ character_index );
+ }
+ if ( external_node_states_matrix.getState( 0, 0 ) instanceof BinaryStates ) {
+ if ( ( external_node_states_matrix.getNumberOfCharacters() * p.getNumberOfBranches() ) != ( getTotalGains()
+ + getTotalLosses() + getTotalUnchanged() ) ) {
+ throw new RuntimeException( "this should not have happened: something is deeply wrong with Fitch parsimony implementation" );
+ }
+ }
+ }
+
+ private void executeForOneCharacter( final Phylogeny p,
+ final Map<PhylogenyNode, SortedSet<STATE_TYPE>> states,
+ final Map<PhylogenyNode, STATE_TYPE> traceback_states,
+ final int character_state_column ) {
+ postOrderTraversal( p, states );
+ preOrderTraversal( p, states, traceback_states, character_state_column );
+ }
+
+ public int getCost() {
+ return _cost;
+ }
+
+ public CharacterStateMatrix<CharacterStateMatrix.GainLossStates> getGainLossMatrix() {
+ if ( !isReturnGainLossMatrix() ) {
+ throw new RuntimeException( "creation of gain-loss matrix has not been enabled" );
+ }
+ return _gain_loss_matrix;
+ }
+
+ public CharacterStateMatrix<STATE_TYPE> getInternalStatesMatrix() {
+ if ( !isReturnInternalStates() ) {
+ throw new RuntimeException( "creation of internal state matrix has not been enabled" );
+ }
+ return _internal_states_matrix_after_traceback;
+ }
+
+ /**
+ * Returns a view of the internal states prior to trace-back.
+ *
+ * @return
+ */
+ public CharacterStateMatrix<List<STATE_TYPE>> getInternalStatesMatrixPriorToTraceback() {
+ if ( !isReturnInternalStates() ) {
+ throw new RuntimeException( "creation of internal state matrix has not been enabled" );
+ }
+ return _internal_states_matrix_prior_to_traceback;
+ }
+
+ private SortedSet<STATE_TYPE> getIntersectionOfStatesOfChildNodes( final Map<PhylogenyNode, SortedSet<STATE_TYPE>> states,
+ final PhylogenyNode node ) throws AssertionError {
+ final SortedSet<STATE_TYPE> states_in_child_nodes = new TreeSet<STATE_TYPE>();
+ for( int i = 0; i < node.getNumberOfDescendants(); ++i ) {
+ final PhylogenyNode node_child = node.getChildNode( i );
+ if ( !states.containsKey( node_child ) ) {
+ throw new AssertionError( "this should not have happened: node [" + node_child.getName()
+ + "] not found in node state map" );
+ }
+ if ( i == 0 ) {
+ states_in_child_nodes.addAll( states.get( node_child ) );
+ }
+ else {
+ states_in_child_nodes.retainAll( states.get( node_child ) );
+ }
+ }
+ return states_in_child_nodes;
+ }
+
+ private Random getRandomGenerator() {
+ return _random_generator;
+ }
+
+ private long getRandomNumberSeed() {
+ return _random_number_seed;
+ }
+
+ private STATE_TYPE getStateAt( final int i, final SortedSet<STATE_TYPE> states ) {
+ final Iterator<STATE_TYPE> it = states.iterator();
+ for( int j = 0; j < i; ++j ) {
+ it.next();
+ }
+ return it.next();
+ }
+
+ private Map<PhylogenyNode, SortedSet<STATE_TYPE>> getStatesForCharacter( final Phylogeny p,
+ final CharacterStateMatrix<STATE_TYPE> matrix,
+ final int character_index ) {
+ final Map<PhylogenyNode, SortedSet<STATE_TYPE>> states = new HashMap<PhylogenyNode, SortedSet<STATE_TYPE>>( matrix
+ .getNumberOfIdentifiers() );
+ for( int indentifier_index = 0; indentifier_index < matrix.getNumberOfIdentifiers(); ++indentifier_index ) {
+ final STATE_TYPE state = matrix.getState( indentifier_index, character_index );
+ if ( state == null ) {
+ throw new IllegalArgumentException( "value at [" + indentifier_index + ", " + character_index
+ + "] is null" );
+ }
+ final SortedSet<STATE_TYPE> l = new TreeSet<STATE_TYPE>();
+ l.add( state );
+ states.put( p.getNode( matrix.getIdentifier( indentifier_index ) ), l );
+ }
+ return states;
+ }
+
+ private Map<PhylogenyNode, STATE_TYPE> getStatesForCharacterForTraceback( final Phylogeny p,
+ final CharacterStateMatrix<STATE_TYPE> matrix,
+ final int character_index ) {
+ final Map<PhylogenyNode, STATE_TYPE> states = new HashMap<PhylogenyNode, STATE_TYPE>( matrix
+ .getNumberOfIdentifiers() );
+ for( int indentifier_index = 0; indentifier_index < matrix.getNumberOfIdentifiers(); ++indentifier_index ) {
+ final STATE_TYPE state = matrix.getState( indentifier_index, character_index );
+ if ( state == null ) {
+ throw new IllegalArgumentException( "value at [" + indentifier_index + ", " + character_index
+ + "] is null" );
+ }
+ states.put( p.getNode( matrix.getIdentifier( indentifier_index ) ), state );
+ }
+ return states;
+ }
+
+ public int getTotalGains() {
+ return _total_gains;
+ }
+
+ public int getTotalLosses() {
+ return _total_losses;
+ }
+
+ public int getTotalUnchanged() {
+ return _total_unchanged;
+ }
+
+ private SortedSet<STATE_TYPE> getUnionOfStatesOfChildNodes( final Map<PhylogenyNode, SortedSet<STATE_TYPE>> states,
+ final PhylogenyNode node ) throws AssertionError {
+ final SortedSet<STATE_TYPE> states_in_child_nodes = new TreeSet<STATE_TYPE>();
+ for( int i = 0; i < node.getNumberOfDescendants(); ++i ) {
+ final PhylogenyNode node_child = node.getChildNode( i );
+ if ( !states.containsKey( node_child ) ) {
+ throw new AssertionError( "this should not have happened: node [" + node_child.getName()
+ + "] not found in node state map" );
+ }
+ states_in_child_nodes.addAll( states.get( node_child ) );
+ }
+ return states_in_child_nodes;
+ }
+
+ private void increaseCost() {
+ ++_cost;
+ }
+
+ private void init() {
+ setReturnInternalStates( RETURN_INTERNAL_STATES_DEFAULT );
+ setReturnGainLossMatrix( RETURN_GAIN_LOSS_MATRIX_DEFAULT );
+ setRandomize( RANDOMIZE_DEFAULT );
+ setUseLast( USE_LAST_DEFAULT );
+ _random_number_seed = RANDOM_NUMBER_SEED_DEFAULT;
+ reset();
+ }
+
+ private void initializeGainLossMatrix( final Phylogeny p,
+ final CharacterStateMatrix<STATE_TYPE> external_node_states_matrix ) {
+ final List<PhylogenyNode> nodes = new ArrayList<PhylogenyNode>();
+ for( final PhylogenyNodeIterator postorder = p.iteratorPostorder(); postorder.hasNext(); ) {
+ nodes.add( postorder.next() );
+ }
+ setGainLossMatrix( new BasicCharacterStateMatrix<CharacterStateMatrix.GainLossStates>( nodes.size(),
+ external_node_states_matrix
+ .getNumberOfCharacters() ) );
+ int identifier_index = 0;
+ for( final PhylogenyNode node : nodes ) {
+ getGainLossMatrix().setIdentifier( identifier_index++,
+ ForesterUtil.isEmpty( node.getName() ) ? node.getId() + "" : node
+ .getName() );
+ }
+ for( int character_index = 0; character_index < external_node_states_matrix.getNumberOfCharacters(); ++character_index ) {
+ getGainLossMatrix().setCharacter( character_index,
+ external_node_states_matrix.getCharacter( character_index ) );
+ }
+ }
+
+ private void initializeInternalStates( final Phylogeny p,
+ final CharacterStateMatrix<STATE_TYPE> external_node_states_matrix ) {
+ final List<PhylogenyNode> internal_nodes = new ArrayList<PhylogenyNode>();
+ for( final PhylogenyNodeIterator postorder = p.iteratorPostorder(); postorder.hasNext(); ) {
+ final PhylogenyNode node = postorder.next();
+ if ( node.isInternal() ) {
+ internal_nodes.add( node );
+ }
+ }
+ setInternalStatesMatrixPriorToTraceback( new BasicCharacterStateMatrix<List<STATE_TYPE>>( internal_nodes.size(),
+ external_node_states_matrix
+ .getNumberOfCharacters() ) );
+ setInternalStatesMatrixTraceback( new BasicCharacterStateMatrix<STATE_TYPE>( internal_nodes.size(),
+ external_node_states_matrix
+ .getNumberOfCharacters() ) );
+ int identifier_index = 0;
+ for( final PhylogenyNode node : internal_nodes ) {
+ getInternalStatesMatrix().setIdentifier( identifier_index,
+ ForesterUtil.isEmpty( node.getName() ) ? node.getId() + "" : node
+ .getName() );
+ getInternalStatesMatrixPriorToTraceback().setIdentifier( identifier_index,
+ ForesterUtil.isEmpty( node.getName() ) ? node
+ .getId()
+ + "" : node.getName() );
+ ++identifier_index;
+ }
+ for( int character_index = 0; character_index < external_node_states_matrix.getNumberOfCharacters(); ++character_index ) {
+ getInternalStatesMatrix().setCharacter( character_index,
+ external_node_states_matrix.getCharacter( character_index ) );
+ getInternalStatesMatrixPriorToTraceback().setCharacter( character_index,
+ external_node_states_matrix
+ .getCharacter( character_index ) );
+ }
+ }
+
+ private boolean isRandomize() {
+ return _randomize;
+ }
+
+ private boolean isReturnGainLossMatrix() {
+ return _return_gain_loss;
+ }
+
+ private boolean isReturnInternalStates() {
+ return _return_internal_states;
+ }
+
+ private boolean isUseLast() {
+ return _use_last;
+ }
+
+ private void postOrderTraversal( final Phylogeny p, final Map<PhylogenyNode, SortedSet<STATE_TYPE>> states )
+ throws AssertionError {
+ for( final PhylogenyNodeIterator postorder = p.iteratorPostorder(); postorder.hasNext(); ) {
+ final PhylogenyNode node = postorder.next();
+ if ( !node.isExternal() ) {
+ SortedSet<STATE_TYPE> states_in_children = getIntersectionOfStatesOfChildNodes( states, node );
+ if ( states_in_children.isEmpty() ) {
+ states_in_children = getUnionOfStatesOfChildNodes( states, node );
+ }
+ states.put( node, states_in_children );
+ }
+ }
+ }
+
+ private void preOrderTraversal( final Phylogeny p,
+ final Map<PhylogenyNode, SortedSet<STATE_TYPE>> states,
+ final Map<PhylogenyNode, STATE_TYPE> traceback_states,
+ final int character_state_column ) throws AssertionError {
+ for( final PhylogenyNodeIterator preorder = p.iteratorPreorder(); preorder.hasNext(); ) {
+ final PhylogenyNode current_node = preorder.next();
+ final SortedSet<STATE_TYPE> current_node_states = states.get( current_node );
+ STATE_TYPE parent_state = null;
+ if ( current_node.isRoot() ) {
+ int i = 0;
+ i = determineIndex( current_node_states, i );
+ traceback_states.put( current_node, getStateAt( i, current_node_states ) );
+ }
+ else {
+ parent_state = traceback_states.get( current_node.getParent() );
+ if ( current_node_states.contains( parent_state ) ) {
+ traceback_states.put( current_node, parent_state );
+ }
+ else {
+ increaseCost();
+ int i = 0;
+ i = determineIndex( current_node_states, i );
+ traceback_states.put( current_node, getStateAt( i, current_node_states ) );
+ }
+ }
+ if ( isReturnInternalStates() ) {
+ if ( !current_node.isExternal() ) {
+ setInternalNodeStatePriorToTraceback( states, character_state_column, current_node );
+ setInternalNodeState( traceback_states, character_state_column, current_node );
+ }
+ }
+ if ( isReturnGainLossMatrix() && !current_node.isRoot() ) {
+ if ( !( parent_state instanceof BinaryStates ) ) {
+ throw new RuntimeException( "attempt to create gain loss matrix for not binary states" );
+ }
+ final BinaryStates parent_binary_state = ( BinaryStates ) parent_state;
+ final BinaryStates current_binary_state = ( BinaryStates ) traceback_states.get( current_node );
+ if ( ( parent_binary_state == PRESENT ) && ( current_binary_state == ABSENT ) ) {
+ ++_total_losses;
+ setGainLossState( character_state_column, current_node, LOSS );
+ }
+ else if ( ( ( parent_binary_state == ABSENT ) || ( parent_binary_state == null ) )
+ && ( current_binary_state == PRESENT ) ) {
+ ++_total_gains;
+ setGainLossState( character_state_column, current_node, GAIN );
+ }
+ else {
+ ++_total_unchanged;
+ if ( current_binary_state == PRESENT ) {
+ setGainLossState( character_state_column, current_node, UNCHANGED_PRESENT );
+ }
+ else if ( current_binary_state == ABSENT ) {
+ setGainLossState( character_state_column, current_node, UNCHANGED_ABSENT );
+ }
+ }
+ }
+ else if ( isReturnGainLossMatrix() && current_node.isRoot() ) {
+ final BinaryStates current_binary_state = ( BinaryStates ) traceback_states.get( current_node );
+ ++_total_unchanged; //new
+ if ( current_binary_state == PRESENT ) {//new
+ setGainLossState( character_state_column, current_node, UNCHANGED_PRESENT );//new
+ }//new
+ else if ( current_binary_state == ABSENT ) {//new
+ setGainLossState( character_state_column, current_node, UNCHANGED_ABSENT );//new
+ }//new
+ // setGainLossState( character_state_column, current_node, UNKNOWN_GAIN_LOSS );
+ }
+ }
+ }
+
+ private void reset() {
+ setCost( 0 );
+ setTotalLosses( 0 );
+ setTotalGains( 0 );
+ setTotalUnchanged( 0 );
+ setRandomGenerator( new Random( getRandomNumberSeed() ) );
+ }
+
+ private void setCost( final int cost ) {
+ _cost = cost;
+ }
+
+ private void setGainLossMatrix( final CharacterStateMatrix<GainLossStates> gain_loss_matrix ) {
+ _gain_loss_matrix = gain_loss_matrix;
+ }
+
+ private void setGainLossState( final int character_state_column,
+ final PhylogenyNode node,
+ final GainLossStates state ) {
+ getGainLossMatrix().setState( ForesterUtil.isEmpty( node.getName() ) ? node.getId() + "" : node.getName(),
+ character_state_column,
+ state );
+ }
+
+ private void setInternalNodeState( final Map<PhylogenyNode, STATE_TYPE> states,
+ final int character_state_column,
+ final PhylogenyNode node ) {
+ getInternalStatesMatrix()
+ .setState( ForesterUtil.isEmpty( node.getName() ) ? node.getId() + "" : node.getName(),
+ character_state_column,
+ states.get( node ) );
+ }
+
+ private void setInternalNodeStatePriorToTraceback( final Map<PhylogenyNode, SortedSet<STATE_TYPE>> states,
+ final int character_state_column,
+ final PhylogenyNode node ) {
+ getInternalStatesMatrixPriorToTraceback().setState( ForesterUtil.isEmpty( node.getName() ) ? node.getId() + ""
+ : node.getName(),
+ character_state_column,
+ toListSorted( states.get( node ) ) );
+ }
+
+ private void setInternalStatesMatrixPriorToTraceback( final CharacterStateMatrix<List<STATE_TYPE>> internal_states_matrix_prior_to_traceback ) {
+ _internal_states_matrix_prior_to_traceback = internal_states_matrix_prior_to_traceback;
+ }
+
+ private void setInternalStatesMatrixTraceback( final CharacterStateMatrix<STATE_TYPE> internal_states_matrix_after_traceback ) {
+ _internal_states_matrix_after_traceback = internal_states_matrix_after_traceback;
+ }
+
+ private void setRandomGenerator( final Random random_generator ) {
+ _random_generator = random_generator;
+ }
+
+ public void setRandomize( final boolean randomize ) {
+ if ( randomize && isUseLast() ) {
+ throw new IllegalArgumentException( "attempt to allways use last state (ordered) if more than one choices and randomization at the same time" );
+ }
+ _randomize = randomize;
+ }
+
+ public void setRandomNumberSeed( final long random_number_seed ) {
+ if ( !isRandomize() ) {
+ throw new IllegalArgumentException( "attempt to set random number generator seed without randomization enabled" );
+ }
+ _random_number_seed = random_number_seed;
+ }
+
+ public void setReturnGainLossMatrix( final boolean return_gain_loss ) {
+ _return_gain_loss = return_gain_loss;
+ }
+
+ public void setReturnInternalStates( final boolean return_internal_states ) {
+ _return_internal_states = return_internal_states;
+ }
+
+ private void setTotalGains( final int total_gains ) {
+ _total_gains = total_gains;
+ }
+
+ private void setTotalLosses( final int total_losses ) {
+ _total_losses = total_losses;
+ }
+
+ private void setTotalUnchanged( final int total_unchanged ) {
+ _total_unchanged = total_unchanged;
+ }
+
+ /**
+ * This sets whether to use the first or last state in the sorted
+ * states at the undecided internal nodes.
+ * For randomized choices set randomize to true (and this to false).
+ *
+ * Note. It might be advisable to set this to false
+ * for BinaryStates if absence at the root is preferred
+ * (given the enum BinaryStates sorts in the following order:
+ * ABSENT, UNKNOWN, PRESENT).
+ *
+ *
+ * @param use_last
+ */
+ public void setUseLast( final boolean use_last ) {
+ if ( use_last && isRandomize() ) {
+ throw new IllegalArgumentException( "attempt to allways use last state (ordered) if more than one choices and randomization at the same time" );
+ }
+ _use_last = use_last;
+ }
+
+ private List<STATE_TYPE> toListSorted( final SortedSet<STATE_TYPE> states ) {
+ final List<STATE_TYPE> l = new ArrayList<STATE_TYPE>( states.size() );
+ for( final STATE_TYPE state : states ) {
+ l.add( state );
+ }
+ return l;
+ }
+}
--- /dev/null
+// $Id:
+// forester -- software libraries and applications
+// for genomics and evolutionary biology research.
+//
+// Copyright (C) 2010 Christian M Zmasek
+// Copyright (C) 2010 Sanford-Burnham Medical Research Institute
+// 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: www.phylosoft.org/forester
+
+package org.forester.evoinference.tools;
+
+import java.util.Random;
+
+import org.forester.msa.BasicMsa;
+import org.forester.msa.Msa;
+
+public class BootstrapResampler {
+
+ private static void copyIdentifiers( final Msa msa, final Msa new_msa ) {
+ for( int i = 0; i < msa.getNumberOfSequences(); ++i ) {
+ new_msa.setIdentifier( i, msa.getIdentifier( i ) );
+ }
+ }
+
+ private static void preconditionCheck( final Msa msa, final int n ) {
+ if ( msa.getLength() < 2 ) {
+ throw new IllegalArgumentException( "Msa length cannot be smaller than two for bootstrap resampling" );
+ }
+ if ( msa.getNumberOfSequences() < 1 ) {
+ throw new IllegalArgumentException( "Attempt to bootstrap resample empty multiple sequence alignment" );
+ }
+ if ( n < 1 ) {
+ throw new IllegalArgumentException( "Number of bootstrap resamples cannot be zero or negative" );
+ }
+ }
+
+ private static void preconditionCheck( final int length, final int n ) {
+ if ( length < 2 ) {
+ throw new IllegalArgumentException( "Msa length cannot be smaller than two for bootstrap resampling" );
+ }
+ if ( n < 1 ) {
+ throw new IllegalArgumentException( "Number of bootstrap resamples cannot be zero or negative" );
+ }
+ }
+
+ public static Msa[] resample( final Msa msa, final int n, final long seed ) {
+ preconditionCheck( msa, n );
+ final Random random = new Random( seed );
+ final Msa[] msas = new Msa[ n ];
+ for( int i = 0; i < n; ++i ) {
+ final Msa new_msa = new BasicMsa( msa.getNumberOfSequences(), msa.getLength(), msa.getType() );
+ msas[ i ] = new_msa;
+ copyIdentifiers( msa, new_msa );
+ for( int col = 0; col < msa.getLength(); ++col ) {
+ final int random_col = random.nextInt( msa.getLength() );
+ for( int row = 0; row < msa.getNumberOfSequences(); ++row ) {
+ new_msa.setResidueAt( row, col, msa.getResidueAt( row, random_col ) );
+ }
+ }
+ }
+ return msas;
+ }
+
+ public static int[][] createResampledColumnPositions( final int length, final int n, final long seed ) {
+ preconditionCheck( length, n );
+ final Random random = new Random( seed );
+ final int[][] columns = new int[ n ][ length ];
+ for( int i = 0; i < n; ++i ) {
+ for( int col = 0; col < length; ++col ) {
+ columns[ i ][ col ] = random.nextInt( length );
+ }
+ }
+ return columns;
+ }
+}