Merge remote-tracking branch 'origin/Tcoffee_JAL-1065' into develop
[jalview.git] / src / jalview / io / AlignFile.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.7)
3  * Copyright (C) 2011 J Procter, AM Waterhouse, J Engelhardt, LM Lui, G Barton, M Clamp, S Searle
4  * 
5  * This file is part of Jalview.
6  * 
7  * Jalview is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License 
9  * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
10  * 
11  * Jalview is distributed in the hope that it will be useful, but 
12  * WITHOUT ANY WARRANTY; without even the implied warranty 
13  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
14  * PURPOSE.  See the GNU General Public License for more details.
15  * 
16  * You should have received a copy of the GNU General Public License along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 package jalview.io;
19
20 import jalview.datamodel.Alignment;
21 import jalview.datamodel.AlignmentAnnotation;
22 import jalview.datamodel.Sequence;
23 import jalview.datamodel.SequenceI;
24
25 import java.io.IOException;
26 import java.util.Enumeration;
27 import java.util.Hashtable;
28 import java.util.Vector;
29
30 /**
31  * DOCUMENT ME!
32  * 
33  * @author $author$
34  * @version $Revision$
35  */
36 public abstract class AlignFile extends FileParse
37 {
38   int noSeqs = 0;
39
40   int maxLength = 0;
41
42   /**
43    * Sequences to be added to form a new alignment.
44    */
45   protected Vector<SequenceI> seqs;
46
47   /**
48    * annotation to be added to generated alignment object
49    */
50   protected Vector annotations;
51
52   /**
53    * Properties to be added to generated alignment object
54    */
55   protected Hashtable properties;
56
57   long start;
58
59   long end;
60
61   boolean jvSuffix = true;
62
63   /**
64    * Creates a new AlignFile object.
65    */
66   public AlignFile()
67   {
68   }
69
70   /**
71    * Constructor which parses the data from a file of some specified type.
72    * 
73    * @param inFile
74    *          Filename to read from.
75    * @param type
76    *          What type of file to read from (File, URL)
77    */
78   public AlignFile(String inFile, String type) throws IOException
79   {
80     super(inFile, type);
81     initData();
82     parse();
83     // sets the index of each sequence in the alignment
84     for( int i=0,c=seqs.size(); i<c; i++ ) {  
85         seqs.get(i).setIndex(i);  
86     }
87   }
88
89   /**
90    * Attempt to read from the position where some other parsing process left
91    * off.
92    * 
93    * @param source
94    * @throws IOException
95    */
96   public AlignFile(FileParse source) throws IOException
97   {
98     super(source);
99     initData();
100     parse();
101     // sets the index of each sequence in the alignment
102     for( int i=0,c=seqs.size(); i<c; i++ ) {  
103         seqs.get(i).setIndex(i);  
104     }
105   }
106
107   /**
108    * Return the seqs Vector
109    */
110   public Vector<SequenceI> getSeqs()
111   {
112     return seqs;
113   }
114
115   /**
116    * Return the Sequences in the seqs Vector as an array of Sequences
117    */
118   public SequenceI[] getSeqsAsArray()
119   {
120     SequenceI[] s = new SequenceI[seqs.size()];
121
122     for (int i = 0; i < seqs.size(); i++)
123     {
124       s[i] = (SequenceI) seqs.elementAt(i);
125     }
126
127     return s;
128   }
129
130   /**
131    * called by AppletFormatAdapter to generate an annotated alignment, rather
132    * than bare sequences.
133    * 
134    * @param al
135    */
136   public void addAnnotations(Alignment al)
137   {
138     addProperties(al);
139     for (int i = 0; i < annotations.size(); i++)
140     {
141       // detect if annotations.elementAt(i) rna secondary structure
142       // if so then do:
143       /*
144        * SequenceFeature[] pairArray =
145        * Rna.GetBasePairsFromAlignmentAnnotation(annotations.elementAt(i));
146        * Rna.HelixMap(pairArray);
147        */
148       AlignmentAnnotation an = (AlignmentAnnotation) annotations
149               .elementAt(i);
150       an.validateRangeAndDisplay();
151       al.addAnnotation(an);
152     }
153
154   }
155
156   /**
157    * Add any additional information extracted from the file to the alignment
158    * properties.
159    * 
160    * @note implicitly called by addAnnotations()
161    * @param al
162    */
163   public void addProperties(Alignment al)
164   {
165     if (properties != null && properties.size() > 0)
166     {
167       Enumeration keys = properties.keys();
168       Enumeration vals = properties.elements();
169       while (keys.hasMoreElements())
170       {
171         al.setProperty(keys.nextElement(), vals.nextElement());
172       }
173     }
174   }
175
176   /**
177    * Store a non-null key-value pair in a hashtable used to set alignment
178    * properties note: null keys will raise an error, null values will result in
179    * the key/value pair being silently ignored.
180    * 
181    * @param key
182    *          - non-null key object
183    * @param value
184    *          - non-null value
185    */
186   protected void setAlignmentProperty(Object key, Object value)
187   {
188     if (key == null)
189     {
190       throw new Error(
191               "Implementation error: Cannot have null alignment property key.");
192     }
193     if (value == null)
194     {
195       return; // null properties are ignored.
196     }
197     if (properties == null)
198     {
199       properties = new Hashtable();
200     }
201     properties.put(key, value);
202   }
203
204   protected Object getAlignmentProperty(Object key)
205   {
206     if (properties != null && key != null)
207     {
208       return properties.get(key);
209     }
210     return null;
211   }
212
213   /**
214    * Initialise objects to store sequence data in.
215    */
216   protected void initData()
217   {
218     seqs = new Vector();
219     annotations = new Vector();
220   }
221
222   /**
223    * DOCUMENT ME!
224    * 
225    * @param s
226    *          DOCUMENT ME!
227    */
228   protected void setSeqs(SequenceI[] s)
229   {
230     seqs = new Vector();
231
232     for (int i = 0; i < s.length; i++)
233     {
234       seqs.addElement(s[i]);
235     }
236   }
237
238   /**
239    * This method must be implemented to parse the contents of the file.
240    */
241   public abstract void parse() throws IOException;
242
243   /**
244    * Print out in alignment file format the Sequences in the seqs Vector.
245    */
246   public abstract String print();
247
248   public void addJVSuffix(boolean b)
249   {
250     jvSuffix = b;
251   }
252
253   /**
254    * A general parser for ids.
255    * 
256    * @String id Id to be parsed
257    */
258   Sequence parseId(String id)
259   {
260     Sequence seq = null;
261     id = id.trim();
262     int space = id.indexOf(" ");
263     if (space > -1)
264     {
265       seq = new Sequence(id.substring(0, space), "");
266       seq.setDescription(id.substring(space + 1));
267     }
268     else
269     {
270       seq = new Sequence(id, "");
271     }
272
273     return seq;
274   }
275
276   /**
277    * Creates the output id. Adds prefix Uniprot format source|id And suffix
278    * Jalview /start-end
279    * 
280    * @String id Id to be parsed
281    */
282   String printId(SequenceI seq)
283   {
284     return seq.getDisplayId(jvSuffix);
285   }
286
287   /**
288    * vector of String[] treeName, newickString pairs
289    */
290   Vector newickStrings = null;
291
292   protected void addNewickTree(String treeName, String newickString)
293   {
294     if (newickStrings == null)
295     {
296       newickStrings = new Vector();
297     }
298     newickStrings.addElement(new String[]
299     { treeName, newickString });
300   }
301
302   protected int getTreeCount()
303   {
304     if (newickStrings == null)
305     {
306       return 0;
307     }
308     return newickStrings.size();
309   }
310
311 }