apparent bug in JpredFile parser where annotation was not being removed from alignmen...
[jalview.git] / src / jalview / io / JPredFile.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer
3  * Copyright (C) 2007 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
18  */
19
20 /**
21  * PredFile.java
22  * JalviewX / Vamsas Project
23  * JPred.seq.concise reader
24  */
25 package jalview.io;
26
27 import java.io.*;
28 import java.util.*;
29
30 import jalview.datamodel.*;
31
32 /**
33  * DOCUMENT ME!
34  *
35  * @author $author$
36  * @version $Revision$
37  */
38 public class JPredFile
39     extends AlignFile
40 {
41   Vector ids;
42   Vector conf;
43   Hashtable Scores; // Hash of names and score vectors
44   Hashtable Symscores; // indexes of symbol annotation properties in sequenceI vector
45   private int QuerySeqPosition;
46
47   /**
48    * Creates a new JPredFile object.
49    *
50    * @param inFile DOCUMENT ME!
51    * @param type DOCUMENT ME!
52    *
53    * @throws IOException DOCUMENT ME!
54    */
55   public JPredFile(String inFile, String type)
56       throws IOException
57   {
58     super(inFile, type);
59   }
60
61   /**
62    * DOCUMENT ME!
63    *
64    * @param QuerySeqPosition DOCUMENT ME!
65    */
66   public void setQuerySeqPosition(int QuerySeqPosition)
67   {
68     this.QuerySeqPosition = QuerySeqPosition;
69   }
70
71   /**
72    * DOCUMENT ME!
73    *
74    * @return DOCUMENT ME!
75    */
76   public int getQuerySeqPosition()
77   {
78     return QuerySeqPosition;
79   }
80
81   /**
82    * DOCUMENT ME!
83    *
84    * @return DOCUMENT ME!
85    */
86   public Hashtable getScores()
87   {
88     return Scores;
89   }
90
91   /**
92    * DOCUMENT ME!
93    *
94    * @return DOCUMENT ME!
95    */
96   public Hashtable getSymscores()
97   {
98     return Symscores;
99   }
100
101   /**
102    * DOCUMENT ME!
103    */
104   public void initData()
105   {
106     super.initData();
107     Scores = new Hashtable();
108     ids = null;
109     conf = null;
110   }
111
112   /**
113    * parse a JPred concise file into a sequence-alignment like object.
114    */
115   public void parse()
116       throws IOException
117   {
118     // JBPNote log.System.out.println("all read in ");
119     String line;
120     QuerySeqPosition = -1;
121     noSeqs = 0;
122
123     Vector seq_entries = new Vector();
124     Vector ids = new Vector();
125     Hashtable Symscores = new Hashtable();
126
127     while ( (line = nextLine()) != null)
128     {
129       // Concise format allows no comments or non comma-formatted data
130       StringTokenizer str = new StringTokenizer(line, ":");
131       String id = "";
132
133       if (!str.hasMoreTokens())
134       {
135         continue;
136       }
137
138       id = str.nextToken();
139
140       String seqsym = str.nextToken();
141       StringTokenizer symbols = new StringTokenizer(seqsym, ",");
142
143       // decide if we have more than just alphanumeric symbols
144       int numSymbols = symbols.countTokens();
145
146       if (numSymbols == 0)
147       {
148         continue;
149       }
150
151       if (seqsym.length() != (2 * numSymbols))
152       {
153         // Set of scalars for some property
154         if (Scores.containsKey(id))
155         {
156           int i = 1;
157
158           while (Scores.containsKey(id + "_" + i))
159           {
160             i++;
161           }
162
163           id = id + "_" + i;
164         }
165
166         Vector scores = new Vector();
167
168         // Typecheck from first entry
169         int i = 0;
170         String ascore = "dead";
171
172         try
173         {
174           // store elements as floats...
175           while (symbols.hasMoreTokens())
176           {
177             ascore = symbols.nextToken();
178
179             Float score = new Float(ascore);
180             scores.addElement( (Object) score);
181           }
182
183           Scores.put(id, scores);
184         }
185         catch (Exception e)
186         {
187           // or just keep them as strings
188           i = scores.size();
189
190           for (int j = 0; j < i; j++)
191           {
192             scores.setElementAt(
193                 (Object) ( (Float) scores.elementAt(j)).toString(), j);
194           }
195
196           scores.addElement( (Object) ascore);
197
198           while (symbols.hasMoreTokens())
199           {
200             ascore = symbols.nextToken();
201             scores.addElement( (Object) ascore);
202           }
203
204           Scores.put(id, scores);
205         }
206       }
207       else if (id.equals("jnetconf"))
208       {
209         // log.debug System.out.println("here");
210         id = "Prediction Confidence";
211         this.conf = new Vector(numSymbols);
212
213         for (int i = 0; i < numSymbols; i++)
214         {
215           conf.setElementAt(symbols.nextToken(), i);
216         }
217       }
218       else
219       {
220         // Sequence or a prediction string (rendered as sequence)
221         StringBuffer newseq = new StringBuffer();
222
223         for (int i = 0; i < numSymbols; i++)
224         {
225           newseq.append(symbols.nextToken());
226         }
227
228         if (id.indexOf(";") > -1)
229         {
230           seq_entries.addElement(newseq);
231
232           int i = 1;
233           String name = id.substring(id.indexOf(";") + 1);
234
235           while (ids.lastIndexOf(name) > -1)
236           {
237             name = id.substring(id.indexOf(";") + 1) + "_" + ++i;
238           }
239
240           if (QuerySeqPosition==-1)
241             QuerySeqPosition = ids.size();
242           ids.addElement(name);
243           noSeqs++;
244         }
245         else
246         {
247           if (id.equals("JNETPRED"))
248           {
249             id = "Predicted Secondary Structure";
250           }
251
252           seq_entries.addElement(newseq.toString());
253           ids.addElement(id);
254           Symscores.put( (Object) id,
255                         (Object)new Integer(ids.size() - 1));
256         }
257       }
258     }
259     /* leave it to the parser user to actually check this.
260              if (noSeqs < 1)
261              {
262         throw new IOException(
263             "JpredFile Parser: No sequence in the prediction!");
264              }*/
265
266     maxLength = seq_entries.elementAt(0).toString().length();
267
268     for (int i = 0; i < ids.size(); i++)
269     {
270       // Add all sequence like objects
271       Sequence newSeq = new Sequence(ids.elementAt(i).toString(),
272                                      seq_entries.elementAt(i).toString(), 1,
273                                      seq_entries.elementAt(i).toString().length());
274
275       if (maxLength != seq_entries.elementAt(i).toString().length())
276       {
277         throw new IOException("JPredConcise: Entry (" +
278                               ids.elementAt(i).toString() +
279                               ") has an unexpected number of columns");
280       }
281
282       if ((newSeq.getName().startsWith("QUERY") || newSeq.getName().startsWith("align;"))&&
283           (QuerySeqPosition == -1))
284       {
285         QuerySeqPosition = seqs.size();
286       }
287
288       seqs.addElement(newSeq);
289     }
290   }
291
292   /**
293    * print
294    *
295    * @return String
296    */
297   public String print()
298   {
299     return "Not Supported";
300   }
301
302   /**
303    * DOCUMENT ME!
304    *
305    * @param args DOCUMENT ME!
306    */
307   public static void main(String[] args)
308   {
309     try
310     {
311       JPredFile blc = new JPredFile(args[0], "File");
312
313       for (int i = 0; i < blc.seqs.size(); i++)
314       {
315         System.out.println( ( (Sequence) blc.seqs.elementAt(i)).getName() +
316                            "\n" +
317                            ( (Sequence) blc.seqs.elementAt(i)).getSequenceAsString() +
318                            "\n");
319       }
320     }
321     catch (java.io.IOException e)
322     {
323       System.err.println("Exception " + e);
324       e.printStackTrace();
325     }
326   }
327
328   Vector annotSeqs = null;
329   /**
330    * removeNonSequences
331    */
332   public void removeNonSequences()
333   {
334     if (annotSeqs != null)
335     {
336       return;
337     }
338     annotSeqs = new Vector();
339     Vector newseqs = new Vector();
340     int i = 0;
341     int j = seqs.size();
342     for (; i < QuerySeqPosition; i++)
343     {
344       annotSeqs.addElement(seqs.elementAt(i));
345     }
346     // check that no stray annotations have been added at the end.
347     {
348       SequenceI sq = (SequenceI) seqs.elementAt(j - 1);
349       if (sq.getName().toUpperCase().startsWith("JPRED"))
350       {
351         annotSeqs.addElement(sq);
352         seqs.removeElementAt(--j);
353       }
354     }
355     for (; i < j; i++)
356     {
357       newseqs.addElement(seqs.elementAt(i));
358     }
359
360     seqs.removeAllElements();
361     seqs = newseqs;
362   }
363 }
364
365 /*
366  StringBuffer out = new StringBuffer();
367
368  out.append("START PRED\n");
369  for (int i = 0; i < s[0].sequence.length(); i++)
370  {
371   out.append(s[0].sequence.substring(i, i + 1) + " ");
372   out.append(s[1].sequence.substring(i, i + 1) + " ");
373   out.append(s[1].score[0].elementAt(i) + " ");
374   out.append(s[1].score[1].elementAt(i) + " ");
375   out.append(s[1].score[2].elementAt(i) + " ");
376   out.append(s[1].score[3].elementAt(i) + " ");
377
378   out.append("\n");
379  }
380  out.append("END PRED\n");
381  return out.toString();
382  }
383
384     public static void main(String[] args)
385  {
386   try
387   {
388     BLCFile blc = new BLCFile(args[0], "File");
389     DrawableSequence[] s = new DrawableSequence[blc.seqs.size()];
390     for (int i = 0; i < blc.seqs.size(); i++)
391     {
392       s[i] = new DrawableSequence( (Sequence) blc.seqs.elementAt(i));
393     }
394     String out = BLCFile.print(s);
395
396     AlignFrame af = new AlignFrame(null, s);
397     af.resize(700, 500);
398     af.show();
399     System.out.println(out);
400   }
401   catch (java.io.IOException e)
402   {
403     System.out.println("Exception " + e);
404   }
405  }
406
407  }
408  */