fixed after refactoring of SequenceFeature[] seq.getSequenceFeatures
[jalview.git] / src / jalview / analysis / SeqsetUtils.java
1 /*\r
2  * Jalview - A Sequence Alignment Editor and Viewer\r
3  * Copyright (C) 2005 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle\r
4  *\r
5  * This program is free software; you can redistribute it and/or\r
6  * modify it under the terms of the GNU General Public License\r
7  * as published by the Free Software Foundation; either version 2\r
8  * of the License, or (at your option) any later version.\r
9  *\r
10  * This program is distributed in the hope that it will be useful,\r
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13  * GNU General Public License for more details.\r
14  *\r
15  * You should have received a copy of the GNU General Public License\r
16  * along with this program; if not, write to the Free Software\r
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA\r
18  */\r
19 package jalview.analysis;\r
20 \r
21 import java.util.*;\r
22 \r
23 import jalview.datamodel.*;\r
24 \r
25 /**\r
26  * <p>Title: </p>\r
27  *\r
28  * <p>Description: </p>\r
29  *\r
30  * <p>Copyright: Copyright (c) 2004</p>\r
31  *\r
32  * <p>Company: Dundee University</p>\r
33  *\r
34  * @author not attributable\r
35  * @version 1.0\r
36  */\r
37 public class SeqsetUtils\r
38 {\r
39 \r
40   /**\r
41    * Store essential properties of a sequence in a hashtable for later recovery\r
42    *  Keys are Name, Start, End, SeqFeatures, PdbId\r
43    * @param seq SequenceI\r
44    * @return Hashtable\r
45    */\r
46   public static Hashtable SeqCharacterHash(SequenceI seq)\r
47   {\r
48     Hashtable sqinfo = new Hashtable();\r
49     sqinfo.put("Name", seq.getName());\r
50     sqinfo.put("Start", new Integer(seq.getStart()));\r
51     sqinfo.put("End", new Integer(seq.getEnd()));\r
52     Vector sfeat = new Vector();\r
53     jalview.datamodel.SequenceFeature[] sfarray=seq.getSequenceFeatures();\r
54     if (sfarray!=null && sfarray.length>0) {\r
55       for (int i=0;i<sfarray.length;i++)\r
56         sfeat.add(sfarray[i]);\r
57     }\r
58     sqinfo.put("SeqFeatures", sfeat);\r
59     sqinfo.put("PdbId",\r
60                (seq.getPDBId() != null) ? seq.getPDBId() : new Vector());\r
61     sqinfo.put("datasetSequence", (seq.getDatasetSequence() !=null) ? seq.getDatasetSequence() : new Sequence("THISISAPLACEHOLDER",""));\r
62     return sqinfo;\r
63   }\r
64 \r
65   /**\r
66    * Recover essential properties of a sequence from a hashtable\r
67    * TODO: replace these methods with something more elegant.\r
68    * @param sq SequenceI\r
69    * @param sqinfo Hashtable\r
70    * @return boolean true if name was not updated from sqinfo Name entry\r
71    */\r
72   public static boolean SeqCharacterUnhash(SequenceI sq, Hashtable sqinfo)\r
73   {\r
74     boolean namePresent = true;\r
75     if (sqinfo==null)\r
76       return false;\r
77     String oldname = (String) sqinfo.get("Name");\r
78     Integer start = (Integer) sqinfo.get("Start");\r
79     Integer end = (Integer) sqinfo.get("End");\r
80     Vector sfeatures = (Vector) sqinfo.get(\r
81         "SeqFeatures");\r
82     Vector pdbid = (Vector) sqinfo.get("PdbId");\r
83     Sequence seqds = (Sequence) sqinfo.get("datasetSequence");\r
84     if (oldname == null)\r
85     {\r
86       namePresent = false;\r
87     }\r
88     else\r
89     {\r
90       sq.setName(oldname);\r
91     }\r
92     if (pdbid!=null && pdbid.size()>0)\r
93     {\r
94       sq.setPDBId(pdbid);\r
95     }\r
96 \r
97     if ( (start != null) && (end != null))\r
98     {\r
99       sq.setStart(start.intValue());\r
100       sq.setEnd(end.intValue());\r
101     }\r
102 \r
103     if ((sfeatures != null) && (sfeatures.size()>0))\r
104     {\r
105       SequenceFeature[] sfarray = (SequenceFeature[]) sfeatures.toArray();\r
106       sq.setSequenceFeatures(sfarray);\r
107     }\r
108 \r
109     if ((seqds!=null) && !(seqds.getName().equals("THISISAPLACEHOLDER") && seqds.getLength()==0)) {\r
110       sq.setDatasetSequence(seqds);\r
111     }\r
112 \r
113     return namePresent;\r
114   }\r
115 \r
116   /**\r
117    * Form of the unique name used in uniquify for the i'th sequence in an ordered vector of sequences.\r
118    * @param i int\r
119    * @return String\r
120    */\r
121   public static String unique_name(int i)\r
122   {\r
123     return new String("Sequence" + i);\r
124   }\r
125 \r
126   /**\r
127    * Generates a hash of SeqCharacterHash properties for each sequence\r
128    * in a sequence set, and optionally renames the sequences to an\r
129    * unambiguous 'safe' name.\r
130    * @param sequences SequenceI[]\r
131    * @param write_names boolean set this to rename each of the sequences to its unique_name(index) name\r
132    * @return Hashtable to be passed to @see deuniquify to recover original names (and properties) for renamed sequences\r
133    */\r
134   public static Hashtable uniquify(SequenceI[] sequences, boolean write_names)\r
135   {\r
136     // Generate a safely named sequence set and a hash to recover the sequence names\r
137     Hashtable map = new Hashtable();\r
138     //String[] un_names = new String[sequences.length];\r
139 \r
140     for (int i = 0; i < sequences.length; i++)\r
141     {\r
142       String safename = unique_name(i);\r
143       map.put(safename, SeqCharacterHash(sequences[i]));\r
144 \r
145       if (write_names)\r
146       {\r
147         sequences[i].setName(safename);\r
148       }\r
149     }\r
150 \r
151 \r
152     return map;\r
153   }\r
154   /**\r
155    * recover unsafe sequence names and original properties for a sequence\r
156    * set using a map generated by @see uniquify(sequences,true)\r
157    * @param map Hashtable\r
158    * @param sequences SequenceI[]\r
159    * @return boolean\r
160    */\r
161   public static boolean deuniquify(Hashtable map, SequenceI[] sequences)\r
162   {\r
163     jalview.analysis.SequenceIdMatcher matcher = new SequenceIdMatcher(sequences);\r
164     SequenceI msq = null;\r
165     Enumeration keys = map.keys();\r
166     Vector unmatched = new Vector();\r
167     for (int i=0, j=sequences.length; i<j; i++)\r
168       unmatched.add(sequences[i]);\r
169     while (keys.hasMoreElements()) {\r
170       Object key = keys.nextElement();\r
171       if (key instanceof String) {\r
172         if ((msq = matcher.findIdMatch((String) key))!=null) {\r
173           Hashtable sqinfo = (Hashtable) map.get(key);\r
174           unmatched.remove(msq);\r
175           SeqCharacterUnhash(msq, sqinfo);\r
176         }\r
177         else\r
178         {\r
179           System.err.println("Can't find '"+((String) key)+"' in uniquified alignment");\r
180         }\r
181       }\r
182     }\r
183     if (unmatched.size()>0) {\r
184       System.err.println("Did not find matches for :");\r
185       for (Enumeration i = unmatched.elements(); i.hasMoreElements(); System.out.println(((SequenceI) i.nextElement()).getName()))\r
186            ;\r
187       return false;\r
188     }\r
189 \r
190     return true;\r
191   }\r
192   /**\r
193    * returns a subset of the sequenceI seuqences,\r
194    * including only those that contain at least one residue.\r
195    * @param sequences SequenceI[]\r
196    * @return SequenceI[]\r
197    */\r
198   public static SequenceI[] getNonEmptySequenceSet(SequenceI[] sequences) {\r
199       // Identify first row of alignment with residues for prediction\r
200       boolean ungapped[] = new boolean[sequences.length];\r
201       int msflen=0;\r
202       for (int i=0,j=sequences.length; i<j;i++) {\r
203         String tempseq = jalview.analysis.AlignSeq.extractGaps(jalview.util.Comparison.GapChars, sequences[i].getSequence());\r
204         if (tempseq.length()==0)\r
205           ungapped[i]=false;\r
206         else {\r
207           ungapped[i]=true;\r
208           msflen++;\r
209         }\r
210       }\r
211       if (msflen==0)\r
212         return null; // no minimal set\r
213       // compose minimal set\r
214       SequenceI[] mset = new SequenceI[msflen];\r
215       for (int i=0,j=sequences.length,k=0; i<j;i++) {\r
216         if (ungapped[i])\r
217           mset[k++] = sequences[i];\r
218       }\r
219       ungapped = null;\r
220       return mset;\r
221   }\r
222 }\r