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