c&p changed
[jalview.git] / src / jalview / io / SequenceFeatureFetcher.java
1 package jalview.io;\r
2 \r
3 import java.io.*;\r
4 import java.util.*;\r
5 import javax.swing.*;\r
6 import jalview.io.*;\r
7 import jalview.gui.*;\r
8 import jalview.datamodel.*;\r
9 \r
10 public class SequenceFeatureFetcher implements Runnable\r
11 {\r
12   AlignmentI align;\r
13   AlignmentPanel ap;\r
14   ArrayList unknownSequences;\r
15   JInternalFrame outputFrame = new JInternalFrame();\r
16   CutAndPasteTransfer output = new CutAndPasteTransfer();\r
17   StringBuffer sbuffer = new StringBuffer();\r
18 \r
19   public SequenceFeatureFetcher(AlignmentI align, AlignmentPanel ap)\r
20   {\r
21     unknownSequences = new ArrayList();\r
22     this.align = align;\r
23     this.ap = ap;\r
24     Thread thread = new Thread(this);\r
25     thread.start();\r
26   }\r
27 \r
28   public void run()\r
29 {\r
30 \r
31   String cache = jalview.bin.Cache.getProperty("UNIPROT_CACHE");\r
32 \r
33   RandomAccessFile out = null;\r
34 \r
35   try{\r
36     if (cache == null)\r
37     {\r
38       jalview.bin.Cache.setProperty("UNIPROT_CACHE", System.getProperty("user.home")+"/uniprot.xml");\r
39       cache = jalview.bin.Cache.getProperty("UNIPROT_CACHE");\r
40     }\r
41 \r
42 \r
43 \r
44     File test = new File(cache);\r
45     if( !test.exists() )\r
46     {\r
47       out = new RandomAccessFile(cache, "rw");\r
48       out.writeBytes("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");\r
49       out.writeBytes("<UNIPROT_CACHE>\n");\r
50     }\r
51     else\r
52     {\r
53       out = new RandomAccessFile(cache, "rw");\r
54       // open exisiting cache and remove </UNIPROT_CACHE> from the end\r
55       long lastLine = 0;\r
56       String data;\r
57       while ( (data = out.readLine()) != null)\r
58       {\r
59         if (data.indexOf("</entry>") > -1)\r
60           lastLine = out.getFilePointer();\r
61 \r
62       }\r
63       out.seek(lastLine);\r
64     }\r
65 \r
66     int seqIndex = 0;\r
67     Vector sequences = align.getSequences();\r
68 \r
69     while (seqIndex < sequences.size())\r
70     {\r
71       ArrayList ids = new ArrayList();\r
72       for (int i = 0; seqIndex < sequences.size() && i < 50; seqIndex++, i++)\r
73       {\r
74         SequenceI sequence = (SequenceI) sequences.get(seqIndex);\r
75         ids.add(sequence.getName());\r
76       }\r
77 \r
78       tryLocalCacheFirst(ids, align);\r
79 \r
80       if (ids.size() > 0)\r
81       {\r
82         StringBuffer remainingIds = new StringBuffer("uniprot:");\r
83         for (int i = 0; i < ids.size(); i++)\r
84           remainingIds.append(ids.get(i) + ";");\r
85 \r
86          EBIFetchClient ebi = new EBIFetchClient();\r
87          String[] result = ebi.fetchData(remainingIds.toString(), "xml", null);\r
88 \r
89         if(result!=null)\r
90           ReadUniprotFile(result, out, align);\r
91       }\r
92 \r
93     }\r
94 \r
95     if (out != null)\r
96     {\r
97       out.writeBytes("</UNIPROT_CACHE>\n");\r
98       out.close();\r
99     }\r
100   }catch(Exception ex){ex.printStackTrace();}\r
101 \r
102   ap.repaint();\r
103   findMissingIds(align);\r
104   if(sbuffer.length()>0)\r
105   {\r
106     outputFrame.setContentPane(output);\r
107     output.setText("Your sequences have been matched to Uniprot. Some of the ids have been\n"\r
108                    +"altered, most likely the start/end residue will have been updated.\n"\r
109                    +"Save your alignment to maintain the updated id.\n\n"+sbuffer.toString());\r
110   Desktop.addInternalFrame(outputFrame, "Sequence names updated ", 600,300);\r
111 \r
112   }\r
113 \r
114   if(unknownSequences.size()>0)\r
115   {\r
116     //ignore for now!!!!!!!!!!\r
117   //  WSWUBlastClient blastClient = new WSWUBlastClient(align, unknownSequences);\r
118   }\r
119 \r
120 }\r
121 \r
122 void ReadUniprotFile(String [] result, RandomAccessFile out, AlignmentI align)\r
123 {\r
124   SequenceI sequence = null;\r
125   Vector features = null;\r
126   String type, description, status, start, end, pdb = null;\r
127 \r
128 \r
129   for (int r = 0; r < result.length; r++)\r
130   {\r
131     if(sequence==null && result[r].indexOf("<name>")>-1)\r
132     {\r
133       long filePointer = 0;\r
134 \r
135       if(out!=null)\r
136       try{\r
137         filePointer=out.getFilePointer();\r
138         out.writeBytes("<entry>\n");\r
139       }catch(Exception ex){}\r
140 \r
141       String seqName = parseElement( result[r], "<name>" , out);\r
142       sequence = align.findName( seqName ) ;\r
143       if(sequence==null)\r
144       {\r
145         sequence = align.findName( seqName.substring(0, seqName.indexOf('_')));\r
146         if(sequence!=null)\r
147         {\r
148           sbuffer.append("changing "+sequence.getName()+" to "+seqName+"\n");\r
149           sequence.setName(seqName);\r
150         }\r
151       }\r
152       if(sequence==null)\r
153       {\r
154         sbuffer.append("UNIPROT updated suggestion is "+result[r]+"\n");\r
155         sequence = align.findName( result[r] ) ;\r
156 \r
157         // this entry has been suggested by ebi.\r
158         // doesn't match id in alignment file\r
159         try   { out.setLength(filePointer);  }  catch (Exception ex) {}\r
160         // now skip to next entry\r
161         while( result[r].indexOf("</entry>")==-1)\r
162           r++;\r
163       }\r
164 \r
165       features = new Vector();\r
166       type=""; start="0"; end="0"; description=""; status=""; pdb="";\r
167 \r
168     }\r
169 \r
170     if(sequence==null)\r
171       continue;\r
172 \r
173      if( result[r].indexOf("<property type=\"pdb accession\"")>-1)\r
174      {\r
175        pdb = parseValue( result[r], "value=" , out);\r
176        sequence.setPDBId(pdb);\r
177      }\r
178 \r
179      if(result[r].indexOf("feature type")>-1)\r
180      {\r
181        type = parseValue( result[r], "type=" , out);\r
182        description = parseValue( result[r], "description=" , null );\r
183        status = parseValue ( result[r], "status=", null);\r
184 \r
185        while( result[r].indexOf("position")==-1)\r
186        {\r
187            r++;  //<location>\r
188        }\r
189       // r++;\r
190        if(result[r].indexOf("begin")>-1)\r
191        {\r
192          start = parseValue( result[r], "position=" , out);\r
193          end = parseValue( result[++r], "position=" , out);\r
194        }\r
195        else\r
196        {\r
197          start = parseValue( result[r], "position=" , out);\r
198          end = parseValue(   result[r], "position=" , null);\r
199        }\r
200        int sstart = Integer.parseInt(start);\r
201        int eend = Integer.parseInt(end);\r
202        if(out!=null)\r
203          try{ out.writeBytes("</feature>\n"); }catch(Exception ex){}\r
204 \r
205          SequenceFeature sf = new SequenceFeature(type,\r
206              sstart,\r
207              eend,\r
208              description,\r
209              status);\r
210          features.add(sf);\r
211      }\r
212 \r
213      if(result[r].indexOf("<sequence")>-1)\r
214      {\r
215        StringBuffer seqString = new StringBuffer();\r
216 \r
217        if(out!=null)\r
218          try  {  out.writeBytes(result[r]+"\n"); }   catch (Exception ex){}\r
219 \r
220        while(result[++r].indexOf("</sequence>")==-1)\r
221        {\r
222          seqString.append(result[r]);\r
223          if(out!=null)\r
224          try  {  out.writeBytes(result[r]+"\n"); }   catch (Exception ex){}\r
225        }\r
226 \r
227        if(out!=null)\r
228          try  {  out.writeBytes(result[r]+"\n"); }   catch (Exception ex){}\r
229 \r
230        StringBuffer nonGapped = new StringBuffer();\r
231        for (int i = 0; i < sequence.getSequence().length(); i++)\r
232        {\r
233          if (!jalview.util.Comparison.isGap(sequence.getCharAt(i)))\r
234            nonGapped.append(sequence.getCharAt(i));\r
235        }\r
236 \r
237        int absStart = seqString.toString().indexOf(nonGapped.toString());\r
238        if(absStart==-1)\r
239        {\r
240          unknownSequences.add(sequence.getName());\r
241          features = null;\r
242          sbuffer.append(sequence.getName()+ " SEQUENCE NOT %100 MATCH \n");\r
243          continue;\r
244        }\r
245 \r
246        int absEnd =   absStart + nonGapped.toString().length();\r
247        absStart+=1;\r
248 \r
249        if(absStart!=sequence.getStart() || absEnd!=sequence.getEnd())\r
250          sbuffer.append("Updated: "+sequence.getName()+" "+\r
251                            sequence.getStart()+"/"+sequence.getEnd()+"  to  "+ absStart+"/"+absEnd+"\n");\r
252 \r
253 \r
254        sequence.setStart(absStart);\r
255        sequence.setEnd(absEnd);\r
256 \r
257      }\r
258 \r
259      if(result[r].indexOf("</entry>")>-1)\r
260      {\r
261        if(features!=null)\r
262          sequence.setSequenceFeatures( features );\r
263        features = null;\r
264        sequence = null;\r
265        if(out!=null)\r
266          try{  out.writeBytes("</entry>\n"); }catch(Exception ex){}\r
267 \r
268      }\r
269   }\r
270 }\r
271 \r
272 void findMissingIds(AlignmentI align)\r
273 {\r
274   String data;\r
275   ArrayList cachedIds = new ArrayList();\r
276 \r
277   try\r
278   {\r
279     BufferedReader in = new BufferedReader(\r
280         new FileReader(jalview.bin.Cache.getProperty("UNIPROT_CACHE")));\r
281 \r
282     while ( (data = in.readLine()) != null)\r
283     {\r
284       if (data.indexOf("name") > -1)\r
285       {\r
286         String name = parseElement(data, "<name>", null);\r
287         cachedIds.add(name);\r
288       }\r
289     }\r
290   }\r
291   catch (Exception ex)\r
292   {   ex.printStackTrace();  }\r
293 \r
294   for(int i=0; i<align.getHeight(); i++)\r
295     if( !cachedIds.contains( align.getSequenceAt(i).getName() ) )\r
296       unknownSequences.add( align.getSequenceAt(i).getName() );\r
297 \r
298 \r
299 }\r
300 \r
301 void tryLocalCacheFirst(ArrayList ids, AlignmentI align)\r
302 {\r
303   ArrayList cacheData = new ArrayList();\r
304   try{\r
305     BufferedReader in = new BufferedReader(\r
306           new FileReader(jalview.bin.Cache.getProperty("UNIPROT_CACHE")));\r
307 \r
308     // read through cache file, if the cache has sequences we're looking for\r
309     // add the lines to a new String array, Readthis new array and\r
310     // make sure we remove the ids from the list to retrieve from EBI\r
311     String data;\r
312     while( ( data=in.readLine())!=null)\r
313     {\r
314       if(data.indexOf("name")>-1)\r
315       {\r
316         String name = parseElement( data, "<name>" , null) ;\r
317         if(ids.contains( name ) )\r
318         {\r
319           cacheData.add("<entry>");\r
320           cacheData.add(data);\r
321           while( data.indexOf("</entry>")==-1)\r
322           {\r
323             data = in.readLine();\r
324             cacheData.add(data);\r
325           }\r
326           cacheData.add(data);\r
327 \r
328           ids.remove( name );\r
329         }\r
330       }\r
331     }\r
332   }\r
333   catch(Exception ex){ex.printStackTrace();}\r
334 \r
335   String [] localData = new String[cacheData.size()];\r
336   cacheData.toArray( localData );\r
337   if(localData!=null && localData.length>0)\r
338     ReadUniprotFile(localData, null, align);\r
339 }\r
340 \r
341 \r
342 String parseValue(String line, String tag, RandomAccessFile out)\r
343 {\r
344   if(out!=null)\r
345     try{  out.writeBytes(line+"\n"); }catch(Exception ex){}\r
346 \r
347 \r
348   int index = line.indexOf(tag)+tag.length()+1;\r
349   if(index==tag.length())\r
350     return "";\r
351 \r
352   return line.substring( index, line.indexOf("\"", index+1) );\r
353 }\r
354 \r
355 \r
356 String parseElement(String line, String tag, RandomAccessFile out)\r
357 {\r
358   if (out != null)\r
359     try\r
360     {\r
361       out.writeBytes(line + "\n");\r
362     }\r
363     catch (Exception ex)\r
364     {}\r
365 \r
366   int index = line.indexOf(tag) + tag.length();\r
367   return line.substring(index, line.indexOf("</"));\r
368 \r
369   }\r
370 }\r