JAL-2795 moved matrix conversion to the ForesterMatrix class
[jalview.git] / src / jalview / ext / forester / ForesterMatrix.java
1 package jalview.ext.forester;
2
3 import jalview.datamodel.SequenceI;
4 import jalview.math.MatrixI;
5 import jalview.util.MessageManager;
6
7 import java.io.IOException;
8 import java.io.Writer;
9 import java.text.DecimalFormat;
10 import java.text.NumberFormat;
11 import java.util.NoSuchElementException;
12 import java.util.stream.IntStream;
13
14 import org.forester.evoinference.matrix.distance.DistanceMatrix;
15 import org.forester.util.ForesterUtil;
16 import org.forester.util.IllegalFormatUseException;
17
18 public class ForesterMatrix implements DistanceMatrix
19 {
20   private final static NumberFormat PHYLIP_FORMATTER = new DecimalFormat(
21           "0.000000"); // straight from forester
22
23   private final MatrixI jalviewMatrix;
24
25   private final String[] identifiers;
26
27   public ForesterMatrix(final MatrixI jalviewInputMatrix,
28           final SequenceI[] matrixSequences)
29   {
30     this.jalviewMatrix = jalviewInputMatrix;
31     this.identifiers = new String[matrixSequences.length];
32
33     int i = 0;
34
35     for (SequenceI sequence : matrixSequences)
36     {
37       identifiers[i] = sequence.getName();
38       i++;
39     }
40
41   }
42
43   public ForesterMatrix(final MatrixI jalviewInputMatrix,
44           final String[] matrixIdentifiers)
45   {
46     this.jalviewMatrix = jalviewInputMatrix;
47     this.identifiers = matrixIdentifiers;
48
49   }
50
51   @Override
52   public String getIdentifier(final int i)
53   {
54     return identifiers[i]; // add handling if index is out of bounds
55   }
56
57
58   @Override
59   public int getIndex(final String identifier)
60   {
61     try {
62     return IntStream.range(0, identifiers.length)
63             .filter(x -> identifier.equals(identifiers[x])).findAny()
64               .getAsInt(); // stream to bypass otherwise having to duplicate the
65                            // list
66                            // with Arrays.aslist
67     }
68     catch (NoSuchElementException ex) {
69       throw new Error(MessageManager.formatMessage(
70               "exception.invalid_matrix_identifier", new String[]
71               { identifier }));
72     }
73   }
74
75   /**
76    * Returns the length of whichever is longest, columns or rows
77    */
78   @Override
79   public int getSize()
80   {
81     return jalviewMatrix.getValues().length;
82   }
83
84   /**
85    * See {@link MatrixI#getValue(int,int)} except that the order of column, row
86    * in the parameters is inverted here (as that is how forester demands it)
87    */
88   @Override
89   public double getValue(final int col, final int row)
90   {
91     return jalviewMatrix.getValue(row, col);
92   }
93
94   @Override
95   public void setIdentifier(final int i, final String identifier)
96   {
97     identifiers[i] = identifier;
98
99   }
100
101   /**
102    * See {@link MatrixI#setValue()} except that the order of column, row in the
103    * parameters is inverted here (as that is how forester demands it)
104    */
105   @Override
106   public void setValue(final int col, final int row, final double distance)
107   {
108     jalviewMatrix.setValue(row, col, distance);
109
110   }
111
112   @Override
113   public StringBuffer toStringBuffer(Format format)
114   {
115     // TODO Auto-generated method stub
116     return null;
117   }
118
119   /**
120    * See {@link MatrixI#getValues()}
121    */
122   @Override
123   public double[][] getValues()
124   {
125     return jalviewMatrix.getValues();
126   }
127
128   @Override
129   public void write(final Writer w) throws IOException // directly copied from
130                                                  // forester
131   {
132     w.write("    ");
133     w.write(getSize() + "");
134     w.write(ForesterUtil.LINE_SEPARATOR);
135     for (int row = 0; row < getSize(); ++row)
136     {
137       if (!ForesterUtil.isEmpty(getIdentifier(row)))
138       {
139         w.write(ForesterUtil.pad(getIdentifier(row), 10, ' ', false)
140                 .toString());
141         w.write(' ');
142         w.write(' ');
143       }
144       else
145       {
146         throw new IllegalFormatUseException(
147                 "Phylip format does not allow empty identifiers");
148       }
149       for (int col = 0; col < getSize(); ++col)
150       {
151         w.write(PHYLIP_FORMATTER.format(getValue(col, row)));
152         if (col < (getSize() - 1))
153         {
154           w.write(' ');
155           w.write(' ');
156         }
157       }
158       if (row < (getSize() - 1))
159       {
160         w.write(ForesterUtil.LINE_SEPARATOR);
161       }
162     }
163
164   }
165
166   public static DistanceMatrix convertJalviewToForester(
167           final MatrixI jalviewInputMatrix,
168           final SequenceI[] matrixSequences)
169   {
170     if (jalviewInputMatrix.width() != jalviewInputMatrix.height())
171     {
172       // some kind of warning?
173     }
174     DistanceMatrix foresterMatrix = new ForesterMatrix(jalviewInputMatrix,
175             matrixSequences);
176     return foresterMatrix;
177
178   }
179
180   public static DistanceMatrix convertJalviewToForester(
181           final MatrixI jalviewInputMatrix,
182           final String[] matrixIdentifiers)
183   {
184     if (jalviewInputMatrix.width() != jalviewInputMatrix.height())
185     {
186       // some kind of warning?
187     }
188
189     DistanceMatrix foresterMatrix = new ForesterMatrix(jalviewInputMatrix,
190             matrixIdentifiers);
191     return foresterMatrix;
192
193   }
194
195
196 }