java 1.1 compatibility
[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.addElement(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 = new SequenceFeature[sfeatures.size()];
118       for (int is=0,isize=sfeatures.size();is<isize;is++)
119       { 
120         sfarray[is] = (SequenceFeature) sfeatures.elementAt(is);
121       }
122       sq.setSequenceFeatures(sfarray);
123     }
124     if (description != null)
125     {
126       sq.setDescription(description);
127     }
128     if ( (seqds != null) &&
129         ! (seqds.getName().equals("THISISAPLACEHOLDER") &&
130            seqds.getLength() == 0))
131     {
132       sq.setDatasetSequence(seqds);
133     }
134
135     return namePresent;
136   }
137
138   /**
139    * Form of the unique name used in uniquify for the i'th sequence in an ordered vector of sequences.
140    * @param i int
141    * @return String
142    */
143   public static String unique_name(int i)
144   {
145     return new String("Sequence" + i);
146   }
147
148   /**
149    * Generates a hash of SeqCharacterHash properties for each sequence
150    * in a sequence set, and optionally renames the sequences to an
151    * unambiguous 'safe' name.
152    * @param sequences SequenceI[]
153    * @param write_names boolean set this to rename each of the sequences to its unique_name(index) name
154    * @return Hashtable to be passed to @see deuniquify to recover original names (and properties) for renamed sequences
155    */
156   public static Hashtable uniquify(SequenceI[] sequences, boolean write_names)
157   {
158     // Generate a safely named sequence set and a hash to recover the sequence names
159     Hashtable map = new Hashtable();
160     //String[] un_names = new String[sequences.length];
161
162     for (int i = 0; i < sequences.length; i++)
163     {
164       String safename = unique_name(i);
165       map.put(safename, SeqCharacterHash(sequences[i]));
166
167       if (write_names)
168       {
169         sequences[i].setName(safename);
170       }
171     }
172
173     return map;
174   }
175
176   /**
177    * recover unsafe sequence names and original properties for a sequence
178    * set using a map generated by @see uniquify(sequences,true)
179    * @param map Hashtable
180    * @param sequences SequenceI[]
181    * @return boolean
182    */
183   public static boolean deuniquify(Hashtable map, SequenceI[] sequences)
184   {
185     return deuniquify(map, sequences, true);
186   }
187   /**
188    * recover unsafe sequence names and original properties for a sequence
189    * set using a map generated by @see uniquify(sequences,true)
190    * @param map Hashtable
191    * @param sequences SequenceI[]
192    * @param quiet when false, don't complain about sequences without any data in the map. 
193    * @return boolean
194    */
195     public static boolean deuniquify(Hashtable map, SequenceI[] sequences, boolean quiet)
196     {
197           jalview.analysis.SequenceIdMatcher matcher = new SequenceIdMatcher(
198         sequences);
199     SequenceI msq = null;
200     Enumeration keys = map.keys();
201     Vector unmatched = new Vector();
202     for (int i = 0, j = sequences.length; i < j; i++)
203     {
204       unmatched.addElement(sequences[i]);
205     }
206     while (keys.hasMoreElements())
207     {
208       Object key = keys.nextElement();
209       if (key instanceof String)
210       {
211         if ( (msq = matcher.findIdMatch( (String) key)) != null)
212         {
213           Hashtable sqinfo = (Hashtable) map.get(key);
214           unmatched.removeElement(msq);
215           SeqCharacterUnhash(msq, sqinfo);
216         }
217         else
218         {
219           if (!quiet)
220             {
221             System.err.println("Can't find '" + ( (String) key) +
222                              "' in uniquified alignment");
223             }
224         }
225       }
226     }
227     if (unmatched.size() > 0 && !quiet)
228     {
229       System.err.println("Did not find matches for :");
230       for (Enumeration i = unmatched.elements(); i.hasMoreElements();
231            System.out.println( ( (SequenceI) i.nextElement()).getName()))
232       {
233         ;
234       }
235       return false;
236     }
237
238     return true;
239   }
240
241   /**
242    * returns a subset of the sequenceI seuqences,
243    * including only those that contain at least one residue.
244    * @param sequences SequenceI[]
245    * @return SequenceI[]
246    */
247   public static SequenceI[] getNonEmptySequenceSet(SequenceI[] sequences)
248   {
249     // Identify first row of alignment with residues for prediction
250     boolean ungapped[] = new boolean[sequences.length];
251     int msflen = 0;
252     for (int i = 0, j = sequences.length; i < j; i++)
253     {
254       String tempseq = jalview.analysis.AlignSeq.extractGaps(
255           jalview.util.Comparison.GapChars,
256           sequences[i].getSequenceAsString());
257
258       if (tempseq.length() == 0)
259       {
260         ungapped[i] = false;
261       }
262       else
263       {
264         ungapped[i] = true;
265         msflen++;
266       }
267     }
268     if (msflen == 0)
269     {
270       return null; // no minimal set
271     }
272     // compose minimal set
273     SequenceI[] mset = new SequenceI[msflen];
274     for (int i = 0, j = sequences.length, k = 0; i < j; i++)
275     {
276       if (ungapped[i])
277       {
278         mset[k++] = sequences[i];
279       }
280     }
281     ungapped = null;
282     return mset;
283   }
284 }