javadoc and quiet flag
[jalview.git] / src / jalview / analysis / SeqsetUtils.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 package jalview.analysis;
20
21 import java.util.*;
22
23 import jalview.datamodel.*;
24
25 /**
26  * <p>Title: </p>
27  *
28  * <p>Description: </p>
29  *
30  * <p>Copyright: Copyright (c) 2004</p>
31  *
32  * <p>Company: Dundee University</p>
33  *
34  * @author not attributable
35  * @version 1.0
36  */
37 public class SeqsetUtils
38 {
39
40   /**
41    * Store essential properties of a sequence in a hashtable for later recovery
42    *  Keys are Name, Start, End, SeqFeatures, PdbId
43    * @param seq SequenceI
44    * @return Hashtable
45    */
46   public static Hashtable SeqCharacterHash(SequenceI seq)
47   {
48     Hashtable sqinfo = new Hashtable();
49     sqinfo.put("Name", seq.getName());
50     sqinfo.put("Start", new Integer(seq.getStart()));
51     sqinfo.put("End", new Integer(seq.getEnd()));
52     if (seq.getDescription() != null)
53     {
54       sqinfo.put("Description", seq.getDescription());
55     }
56     Vector sfeat = new Vector();
57     jalview.datamodel.SequenceFeature[] sfarray = seq.getSequenceFeatures();
58     if (sfarray != null && sfarray.length > 0)
59     {
60       for (int i = 0; i < sfarray.length; i++)
61       {
62         sfeat.add(sfarray[i]);
63       }
64     }
65     sqinfo.put("SeqFeatures", sfeat);
66     sqinfo.put("PdbId",
67                (seq.getPDBId() != null) ? seq.getPDBId() : new Vector());
68     sqinfo.put("datasetSequence",
69                (seq.getDatasetSequence() != null) ? seq.getDatasetSequence() :
70                new Sequence("THISISAPLACEHOLDER", ""));
71     return sqinfo;
72   }
73
74   /**
75    * Recover essential properties of a sequence from a hashtable
76    * TODO: replace these methods with something more elegant.
77    * @param sq SequenceI
78    * @param sqinfo Hashtable
79    * @return boolean true if name was not updated from sqinfo Name entry
80    */
81   public static boolean SeqCharacterUnhash(SequenceI sq, Hashtable sqinfo)
82   {
83     boolean namePresent = true;
84     if (sqinfo == null)
85     {
86       return false;
87     }
88     String oldname = (String) sqinfo.get("Name");
89     Integer start = (Integer) sqinfo.get("Start");
90     Integer end = (Integer) sqinfo.get("End");
91     Vector sfeatures = (Vector) sqinfo.get(
92         "SeqFeatures");
93     Vector pdbid = (Vector) sqinfo.get("PdbId");
94     String description = (String) sqinfo.get("Description");
95     Sequence seqds = (Sequence) sqinfo.get("datasetSequence");
96     if (oldname == null)
97     {
98       namePresent = false;
99     }
100     else
101     {
102       sq.setName(oldname);
103     }
104     if (pdbid != null && pdbid.size() > 0)
105     {
106       sq.setPDBId(pdbid);
107     }
108
109     if ( (start != null) && (end != null))
110     {
111       sq.setStart(start.intValue());
112       sq.setEnd(end.intValue());
113     }
114
115     if ( (sfeatures != null) && (sfeatures.size() > 0))
116     {
117       SequenceFeature[] sfarray = (SequenceFeature[]) sfeatures.toArray();
118       sq.setSequenceFeatures(sfarray);
119     }
120     if (description != null)
121     {
122       sq.setDescription(description);
123     }
124     if ( (seqds != null) &&
125         ! (seqds.getName().equals("THISISAPLACEHOLDER") &&
126            seqds.getLength() == 0))
127     {
128       sq.setDatasetSequence(seqds);
129     }
130
131     return namePresent;
132   }
133
134   /**
135    * Form of the unique name used in uniquify for the i'th sequence in an ordered vector of sequences.
136    * @param i int
137    * @return String
138    */
139   public static String unique_name(int i)
140   {
141     return new String("Sequence" + i);
142   }
143
144   /**
145    * Generates a hash of SeqCharacterHash properties for each sequence
146    * in a sequence set, and optionally renames the sequences to an
147    * unambiguous 'safe' name.
148    * @param sequences SequenceI[]
149    * @param write_names boolean set this to rename each of the sequences to its unique_name(index) name
150    * @return Hashtable to be passed to @see deuniquify to recover original names (and properties) for renamed sequences
151    */
152   public static Hashtable uniquify(SequenceI[] sequences, boolean write_names)
153   {
154     // Generate a safely named sequence set and a hash to recover the sequence names
155     Hashtable map = new Hashtable();
156     //String[] un_names = new String[sequences.length];
157
158     for (int i = 0; i < sequences.length; i++)
159     {
160       String safename = unique_name(i);
161       map.put(safename, SeqCharacterHash(sequences[i]));
162
163       if (write_names)
164       {
165         sequences[i].setName(safename);
166       }
167     }
168
169     return map;
170   }
171
172   /**
173    * recover unsafe sequence names and original properties for a sequence
174    * set using a map generated by @see uniquify(sequences,true)
175    * @param map Hashtable
176    * @param sequences SequenceI[]
177    * @return boolean
178    */
179   public static boolean deuniquify(Hashtable map, SequenceI[] sequences)
180   {
181     return deuniquify(map, sequences, true);
182   }
183   /**
184    * recover unsafe sequence names and original properties for a sequence
185    * set using a map generated by @see uniquify(sequences,true)
186    * @param map Hashtable
187    * @param sequences SequenceI[]
188    * @param quiet when false, don't complain about sequences without any data in the map. 
189    * @return boolean
190    */
191     public static boolean deuniquify(Hashtable map, SequenceI[] sequences, boolean quiet)
192     {
193           jalview.analysis.SequenceIdMatcher matcher = new SequenceIdMatcher(
194         sequences);
195     SequenceI msq = null;
196     Enumeration keys = map.keys();
197     Vector unmatched = new Vector();
198     for (int i = 0, j = sequences.length; i < j; i++)
199     {
200       unmatched.add(sequences[i]);
201     }
202     while (keys.hasMoreElements())
203     {
204       Object key = keys.nextElement();
205       if (key instanceof String)
206       {
207         if ( (msq = matcher.findIdMatch( (String) key)) != null)
208         {
209           Hashtable sqinfo = (Hashtable) map.get(key);
210           unmatched.remove(msq);
211           SeqCharacterUnhash(msq, sqinfo);
212         }
213         else
214         {
215           if (!quiet)
216             {
217             System.err.println("Can't find '" + ( (String) key) +
218                              "' in uniquified alignment");
219             }
220         }
221       }
222     }
223     if (unmatched.size() > 0 && !quiet)
224     {
225       System.err.println("Did not find matches for :");
226       for (Enumeration i = unmatched.elements(); i.hasMoreElements();
227            System.out.println( ( (SequenceI) i.nextElement()).getName()))
228       {
229         ;
230       }
231       return false;
232     }
233
234     return true;
235   }
236
237   /**
238    * returns a subset of the sequenceI seuqences,
239    * including only those that contain at least one residue.
240    * @param sequences SequenceI[]
241    * @return SequenceI[]
242    */
243   public static SequenceI[] getNonEmptySequenceSet(SequenceI[] sequences)
244   {
245     // Identify first row of alignment with residues for prediction
246     boolean ungapped[] = new boolean[sequences.length];
247     int msflen = 0;
248     for (int i = 0, j = sequences.length; i < j; i++)
249     {
250       String tempseq = jalview.analysis.AlignSeq.extractGaps(
251           jalview.util.Comparison.GapChars,
252           sequences[i].getSequenceAsString());
253
254       if (tempseq.length() == 0)
255       {
256         ungapped[i] = false;
257       }
258       else
259       {
260         ungapped[i] = true;
261         msflen++;
262       }
263     }
264     if (msflen == 0)
265     {
266       return null; // no minimal set
267     }
268     // compose minimal set
269     SequenceI[] mset = new SequenceI[msflen];
270     for (int i = 0, j = sequences.length, k = 0; i < j; i++)
271     {
272       if (ungapped[i])
273       {
274         mset[k++] = sequences[i];
275       }
276     }
277     ungapped = null;
278     return mset;
279   }
280 }