e9f49bdc87df665f5c2da6e6d4c52a14c24a249d
[vamsas.git] / src / uk / ac / vamsas / objects / utils / SeqAln.java
1 /*
2  * Created on 17-May-2005
3  *
4  * TODO To change the template for this generated file go to
5  * Window - Preferences - Java - Code Style - Code Templates
6  */
7 package uk.ac.vamsas.objects.utils;
8
9 import java.io.BufferedOutputStream;
10 import java.io.BufferedReader;
11 import java.io.BufferedWriter;
12 import java.io.IOException;
13 import java.io.InputStream;
14 import java.io.InputStreamReader;
15 import java.util.Hashtable;
16 import java.util.StringTokenizer;
17 import java.util.Vector;
18 import java.util.regex.Pattern;
19
20 import uk.ac.vamsas.objects.core.*;
21
22 /**
23  * @author jimp
24  * 
25  * TODO To change the template for this generated type comment go to Window -
26  * Preferences - Java - Code Style - Code Templates
27  */
28 public class SeqAln extends uk.ac.vamsas.objects.core.Alignment {
29
30   public static Sequence[] ReadClustalFile(InputStream os) throws Exception {
31     System.err.println("NOT FULLY IMPLEMENTED!"); // TODO: Finish adapting this method
32     Pattern nonGap = Pattern.compile("[A-Z*0-9]", Pattern.CASE_INSENSITIVE);
33     String gapchars = "";
34     char gapchar = '-';
35
36     int i = 0;
37     boolean flag = false;
38
39     Vector headers = new Vector();
40     Hashtable seqhash = new Hashtable();
41     Sequence[] seqs = null;
42     int noSeqs = 0;
43     String line;
44
45     try {
46       BufferedReader ins = new BufferedReader(new InputStreamReader(os));
47       while ((line = ins.readLine()) != null) {
48         if (line.indexOf(" ") != 0) {
49           java.util.StringTokenizer str = new StringTokenizer(line, " ");
50           String id = "";
51
52           if (str.hasMoreTokens()) {
53             id = str.nextToken();
54             if (id.equals("CLUSTAL")) {
55               flag = true;
56             } else {
57               if (flag) {
58                 StringBuffer tempseq;
59                 if (seqhash.containsKey(id)) {
60                   tempseq = (StringBuffer) seqhash.get(id);
61                 } else {
62                   tempseq = new StringBuffer();
63                   seqhash.put(id, tempseq);
64                 }
65
66                 if (!(headers.contains(id))) {
67                   headers.addElement(id);
68                 }
69
70                 tempseq.append(str.nextToken());
71               }
72             }
73           }
74         }
75       }
76
77     } catch (IOException e) {
78       throw (new Exception("Exception parsing clustal file ", e));
79     }
80
81     if (flag) {
82       noSeqs = headers.size();
83
84       // Add sequences to the hash
85       seqs = new Sequence[headers.size()];
86       for (i = 0; i < headers.size(); i++) {
87         if (seqhash.get(headers.elementAt(i)) != null) {
88           // TODO: develop automatic dictionary typing for sequences
89           Sequence newSeq = Seq.newSequence(headers.elementAt(i).toString(),
90               seqhash.get(headers.elementAt(i).toString()).toString(),
91               SymbolDictionary.STANDARD_AA,0,0);
92
93           seqs[i] = newSeq;
94
95         } else {
96           throw (new Exception("Bizarreness! Can't find sequence for "
97               + headers.elementAt(i)));
98         }
99       }
100     }
101     return seqs;
102   }
103
104   public static void WriteClustalWAlignment(java.io.OutputStream os,
105       Alignment seqAl) throws IOException {
106     System.err.println("NOT FULLY IMPLEMENTED!"); // TODO: Finish adapting this method
107     AlignmentSequence[] s = seqAl.getAlignmentSequence();
108
109     java.io.BufferedWriter out = new BufferedWriter(
110         new java.io.OutputStreamWriter(os));
111
112     out.write("CLUSTAL\n\n");
113
114     int max = 0;
115     int maxid = 0;
116
117     int i = 0;
118
119     while (i < s.length && s[i] != null) {
120       String tmp = s[i].getId();
121
122       if (s[i].getSequence().length() > max) {
123         max = s[i].getSequence().length();
124       }
125       if (tmp.length() > maxid) {
126         maxid = tmp.length();
127       }
128       i++;
129     }
130
131     if (maxid < 15) {
132       maxid = 15;
133     }
134     maxid++;
135     int len = 60;
136     int nochunks = max / len + 1;
137
138     for (i = 0; i < nochunks; i++) {
139       int j = 0;
140       while (j < s.length && s[j] != null) {
141         out.write(new Format("%-" + maxid + "s").form(s[j].getId() + " "));
142         int start = i * len;
143         int end = start + len;
144
145         if (end < s[j].getSequence().length() && start < s[j].getSequence().length()) {
146           out.write(s[j].getSequence().substring(start, end) + "\n");
147         } else {
148           if (start < s[j].getSequence().length()) {
149             out.write(s[j].getSequence().substring(start) + "\n");
150           }
151         }
152         j++;
153       }
154       out.write("\n");
155
156     }
157   }
158   /**
159    * manufacture an alignment/dataset from an array of sequences
160    * @param origin
161    * @param seqs
162    * @return
163    * @throws Exception
164    */
165   public static Alignment make_Alignment(Entry origin,
166       Sequence[] seqs) throws Exception {
167     System.err.println("NOT FULLY IMPLEMENTED!"); // TODO: Finish adapting this method
168     Alignment al = new Alignment();
169     al.setProvenance(ProvenanceStuff.newProvenance(origin));
170     
171     Pattern nonGap = Pattern.compile("[A-Z*0-9]", Pattern.CASE_INSENSITIVE);
172     boolean gapsset = false;
173     char gapchar = '-';
174     int seqLength = 0;
175
176     for (int i = 0, nseq = seqs.length; i < nseq; i++) {
177       String seq = seqs[i].getSequence();
178       String gaps = nonGap.matcher(seq).replaceAll("");
179       if (seqLength == 0) {
180         seqLength = seq.length();
181       } else if (seqLength != seq.length())
182         throw (new Exception(i + "th Sequence (>" + seqs[i].getId()
183             + ") is not aligned.\n"));// TODO: move this to assertions part of
184                                       // Alignment
185
186       // common check for any sequence...
187       if (gaps != null && gaps.length() > 0) {
188         if (!gapsset)
189           gapchar = gaps.charAt(0);
190         for (int c = 0, gc = gaps.length(); c < gc; c++) {
191           if (gapchar != gaps.charAt(c)) {
192             throw (new IOException("Inconsistent gap characters in sequence "
193                 + i + ": '" + seq + "'"));
194           }
195         }
196       }
197       AlignmentSequence sq = new AlignmentSequence();
198       // TODO: use as basis of default AlignSequence(Sequence) constructor.
199       sq.setSequence(seq);
200       sq.setName(seqs[i].getId());
201       sq.setRefid(seqs[i].getVorbaId());
202       sq.setStart(seqs[i].getStart());
203       sq.setEnd(seqs[i].getEnd());
204       al.addAlignmentSequence(sq);
205     }
206     al.setGapChar(String.valueOf(gapchar));
207     return al;
208   }
209
210   public static Alignment read_FastaAlignment(InputStream os, Entry entry)
211       throws Exception {
212     Sequence[] seqs;
213     System.err.println("NOT FULLY IMPLEMENTED!"); // TODO: Finish adapting this method
214     try {
215       seqs = SeqSet.read_SeqFasta(os);
216       if (seqs == null)
217         throw (new Exception("Empty alignment stream!\n"));
218     } catch (Exception e) {
219       throw new Exception("Invalid fasta alignment\n", e);
220     }
221     
222     return make_Alignment(entry, seqs);
223   }
224
225   public static Alignment read_ClustalAlignment(InputStream os, Entry entry)
226       throws Exception {
227     Sequence[] seqs;
228     try {
229       seqs = SeqAln.ReadClustalFile(os);
230       if (seqs == null)
231         throw (new Exception("Empty alignment stream!\n"));
232     } catch (Exception e) {
233       throw new Exception("Invalid fasta alignment\n", e);
234     }
235     System.err.println("NOT FULLY IMPLEMENTED!"); // TODO: Finish adapting this method
236     return make_Alignment(entry, seqs);
237   }
238 }