package jalview.ext.forester; import jalview.datamodel.SequenceI; import jalview.math.MatrixI; import jalview.util.MessageManager; import java.io.IOException; import java.io.Writer; import java.text.DecimalFormat; import java.text.NumberFormat; import java.util.NoSuchElementException; import java.util.stream.IntStream; import org.forester.evoinference.matrix.distance.DistanceMatrix; import org.forester.util.ForesterUtil; import org.forester.util.IllegalFormatUseException; public class ForesterMatrix implements DistanceMatrix { private final static NumberFormat PHYLIP_FORMATTER = new DecimalFormat( "0.000000"); // straight from forester private final MatrixI jalviewMatrix; private final String[] identifiers; public ForesterMatrix(final MatrixI jalviewInputMatrix, final SequenceI[] matrixSequences) { this.jalviewMatrix = jalviewInputMatrix; this.identifiers = new String[matrixSequences.length]; int i = 0; for (SequenceI sequence : matrixSequences) { identifiers[i] = sequence.getName(); i++; } } public ForesterMatrix(final MatrixI jalviewInputMatrix, final String[] matrixIdentifiers) { this.jalviewMatrix = jalviewInputMatrix; this.identifiers = matrixIdentifiers; } @Override public String getIdentifier(final int i) { return identifiers[i]; // add handling if index is out of bounds } @Override public int getIndex(final String identifier) { try { return IntStream.range(0, identifiers.length) .filter(x -> identifier.equals(identifiers[x])).findAny() .getAsInt(); // stream to bypass otherwise having to duplicate the // list // with Arrays.aslist } catch (NoSuchElementException ex) { throw new Error(MessageManager.formatMessage( "exception.invalid_matrix_identifier", new String[] { identifier })); } } /** * Returns the length of whichever is longest, columns or rows */ @Override public int getSize() { return jalviewMatrix.getValues().length; } /** * See {@link MatrixI#getValue(int,int)} except that the order of column, row * in the parameters is inverted here (as that is how forester demands it) */ @Override public double getValue(final int col, final int row) { return jalviewMatrix.getValue(row, col); } @Override public void setIdentifier(final int i, final String identifier) { identifiers[i] = identifier; } /** * See {@link MatrixI#setValue()} except that the order of column, row in the * parameters is inverted here (as that is how forester demands it) */ @Override public void setValue(final int col, final int row, final double distance) { jalviewMatrix.setValue(row, col, distance); } @Override public StringBuffer toStringBuffer(Format format) { // TODO Auto-generated method stub return null; } /** * See {@link MatrixI#getValues()} */ @Override public double[][] getValues() { return jalviewMatrix.getValues(); } @Override public void write(final Writer w) throws IOException // directly copied from // forester { 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); } } } public static DistanceMatrix convertJalviewToForester( final MatrixI jalviewInputMatrix, final SequenceI[] matrixSequences) { return DataConversions.createForesterDistanceMatrix( jalviewInputMatrix, matrixSequences); } public static DistanceMatrix convertJalviewToForester( final MatrixI jalviewInputMatrix, final String[] matrixIdentifiers) { return DataConversions.createForesterDistanceMatrix( jalviewInputMatrix, matrixIdentifiers); } }