new place for sequencefeaturefetcher
[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(false);\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     output.formatForOutput();\r
107     outputFrame.setContentPane(output);\r
108     output.setText("Your sequences have been matched to Uniprot. Some of the ids have been\n"\r
109                    +"altered, most likely the start/end residue will have been updated.\n"\r
110                    +"Save your alignment to maintain the updated id.\n\n"+sbuffer.toString());\r
111   Desktop.addInternalFrame(outputFrame, "Sequence names updated ", 600,300);\r
112 \r
113   }\r
114 \r
115   if(unknownSequences.size()>0)\r
116   {\r
117     //ignore for now!!!!!!!!!!\r
118   //  WSWUBlastClient blastClient = new WSWUBlastClient(align, unknownSequences);\r
119   }\r
120 \r
121 }\r
122 \r
123 void ReadUniprotFile(String [] result, RandomAccessFile out, AlignmentI align)\r
124 {\r
125   SequenceI sequence = null;\r
126   Vector features = null;\r
127   String type, description, status, start, end, pdb = null;\r
128 \r
129 \r
130   for (int r = 0; r < result.length; r++)\r
131   {\r
132     if(sequence==null && result[r].indexOf("<name>")>-1)\r
133     {\r
134       long filePointer = 0;\r
135 \r
136       if(out!=null)\r
137       try{\r
138         filePointer=out.getFilePointer();\r
139         out.writeBytes("<entry>\n");\r
140       }catch(Exception ex){}\r
141 \r
142       String seqName = parseElement( result[r], "<name>" , out);\r
143       sequence = align.findName( seqName ) ;\r
144       if(sequence==null)\r
145       {\r
146         sequence = align.findName( seqName.substring(0, seqName.indexOf('_')));\r
147         if(sequence!=null)\r
148         {\r
149           sbuffer.append("changing "+sequence.getName()+" to "+seqName+"\n");\r
150           sequence.setName(seqName);\r
151         }\r
152       }\r
153       if(sequence==null)\r
154       {\r
155         sbuffer.append("UNIPROT updated suggestion is "+result[r]+"\n");\r
156         sequence = align.findName( result[r] ) ;\r
157 \r
158         // this entry has been suggested by ebi.\r
159         // doesn't match id in alignment file\r
160         try   { out.setLength(filePointer);  }  catch (Exception ex) {}\r
161         // now skip to next entry\r
162         while( result[r].indexOf("</entry>")==-1)\r
163           r++;\r
164       }\r
165 \r
166       features = new Vector();\r
167       type=""; start="0"; end="0"; description=""; status=""; pdb="";\r
168 \r
169     }\r
170 \r
171     if(sequence==null)\r
172       continue;\r
173 \r
174      if( result[r].indexOf("<property type=\"pdb accession\"")>-1)\r
175      {\r
176        pdb = parseValue( result[r], "value=" , out);\r
177        sequence.setPDBId(pdb);\r
178      }\r
179 \r
180      if(result[r].indexOf("feature type")>-1)\r
181      {\r
182        type = parseValue( result[r], "type=" , out);\r
183        description = parseValue( result[r], "description=" , null );\r
184        status = parseValue ( result[r], "status=", null);\r
185 \r
186        while( result[r].indexOf("position")==-1)\r
187        {\r
188            r++;  //<location>\r
189        }\r
190       // r++;\r
191        if(result[r].indexOf("begin")>-1)\r
192        {\r
193          start = parseValue( result[r], "position=" , out);\r
194          end = parseValue( result[++r], "position=" , out);\r
195        }\r
196        else\r
197        {\r
198          start = parseValue( result[r], "position=" , out);\r
199          end = parseValue(   result[r], "position=" , null);\r
200        }\r
201        int sstart = Integer.parseInt(start);\r
202        int eend = Integer.parseInt(end);\r
203        if(out!=null)\r
204          try{ out.writeBytes("</feature>\n"); }catch(Exception ex){}\r
205 \r
206          SequenceFeature sf = new SequenceFeature(type,\r
207              sstart,\r
208              eend,\r
209              description,\r
210              status);\r
211          features.add(sf);\r
212      }\r
213 \r
214      if(result[r].indexOf("<sequence")>-1)\r
215      {\r
216        StringBuffer seqString = new StringBuffer();\r
217 \r
218        if(out!=null)\r
219          try  {  out.writeBytes(result[r]+"\n"); }   catch (Exception ex){}\r
220 \r
221        while(result[++r].indexOf("</sequence>")==-1)\r
222        {\r
223          seqString.append(result[r]);\r
224          if(out!=null)\r
225          try  {  out.writeBytes(result[r]+"\n"); }   catch (Exception ex){}\r
226        }\r
227 \r
228        if(out!=null)\r
229          try  {  out.writeBytes(result[r]+"\n"); }   catch (Exception ex){}\r
230 \r
231        StringBuffer nonGapped = new StringBuffer();\r
232        for (int i = 0; i < sequence.getSequence().length(); i++)\r
233        {\r
234          if (!jalview.util.Comparison.isGap(sequence.getCharAt(i)))\r
235            nonGapped.append(sequence.getCharAt(i));\r
236        }\r
237 \r
238        int absStart = seqString.toString().indexOf(nonGapped.toString());\r
239        if(absStart==-1)\r
240        {\r
241          unknownSequences.add(sequence.getName());\r
242          features = null;\r
243          sbuffer.append(sequence.getName()+ " SEQUENCE NOT %100 MATCH \n");\r
244          continue;\r
245        }\r
246 \r
247        int absEnd =   absStart + nonGapped.toString().length();\r
248        absStart+=1;\r
249 \r
250        if(absStart!=sequence.getStart() || absEnd!=sequence.getEnd())\r
251          sbuffer.append("Updated: "+sequence.getName()+" "+\r
252                            sequence.getStart()+"/"+sequence.getEnd()+"  to  "+ absStart+"/"+absEnd+"\n");\r
253 \r
254 \r
255        sequence.setStart(absStart);\r
256        sequence.setEnd(absEnd);\r
257 \r
258      }\r
259 \r
260      if(result[r].indexOf("</entry>")>-1)\r
261      {\r
262        if(features!=null)\r
263          sequence.setSequenceFeatures( features );\r
264        features = null;\r
265        sequence = null;\r
266        if(out!=null)\r
267          try{  out.writeBytes("</entry>\n"); }catch(Exception ex){}\r
268 \r
269      }\r
270   }\r
271 }\r
272 \r
273 void findMissingIds(AlignmentI align)\r
274 {\r
275   String data;\r
276   ArrayList cachedIds = new ArrayList();\r
277 \r
278   try\r
279   {\r
280     BufferedReader in = new BufferedReader(\r
281         new FileReader(jalview.bin.Cache.getProperty("UNIPROT_CACHE")));\r
282 \r
283     while ( (data = in.readLine()) != null)\r
284     {\r
285       if (data.indexOf("name") > -1)\r
286       {\r
287         String name = parseElement(data, "<name>", null);\r
288         cachedIds.add(name);\r
289       }\r
290     }\r
291   }\r
292   catch (Exception ex)\r
293   {   ex.printStackTrace();  }\r
294 \r
295   for(int i=0; i<align.getHeight(); i++)\r
296     if( !cachedIds.contains( align.getSequenceAt(i).getName() ) )\r
297       unknownSequences.add( align.getSequenceAt(i).getName() );\r
298 \r
299 \r
300 }\r
301 \r
302 void tryLocalCacheFirst(ArrayList ids, AlignmentI align)\r
303 {\r
304   ArrayList cacheData = new ArrayList();\r
305   try{\r
306     BufferedReader in = new BufferedReader(\r
307           new FileReader(jalview.bin.Cache.getProperty("UNIPROT_CACHE")));\r
308 \r
309     // read through cache file, if the cache has sequences we're looking for\r
310     // add the lines to a new String array, Readthis new array and\r
311     // make sure we remove the ids from the list to retrieve from EBI\r
312     String data;\r
313     while( ( data=in.readLine())!=null)\r
314     {\r
315       if(data.indexOf("name")>-1)\r
316       {\r
317         String name = parseElement( data, "<name>" , null) ;\r
318         if(ids.contains( name ) )\r
319         {\r
320           cacheData.add("<entry>");\r
321           cacheData.add(data);\r
322           while( data.indexOf("</entry>")==-1)\r
323           {\r
324             data = in.readLine();\r
325             cacheData.add(data);\r
326           }\r
327           cacheData.add(data);\r
328 \r
329           ids.remove( name );\r
330         }\r
331       }\r
332     }\r
333   }\r
334   catch(Exception ex){ex.printStackTrace();}\r
335 \r
336   String [] localData = new String[cacheData.size()];\r
337   cacheData.toArray( localData );\r
338   if(localData!=null && localData.length>0)\r
339     ReadUniprotFile(localData, null, align);\r
340 }\r
341 \r
342 \r
343 String parseValue(String line, String tag, RandomAccessFile out)\r
344 {\r
345   if(out!=null)\r
346     try{  out.writeBytes(line+"\n"); }catch(Exception ex){}\r
347 \r
348 \r
349   int index = line.indexOf(tag)+tag.length()+1;\r
350   if(index==tag.length())\r
351     return "";\r
352 \r
353   return line.substring( index, line.indexOf("\"", index+1) );\r
354 }\r
355 \r
356 \r
357 String parseElement(String line, String tag, RandomAccessFile out)\r
358 {\r
359   if (out != null)\r
360     try\r
361     {\r
362       out.writeBytes(line + "\n");\r
363     }\r
364     catch (Exception ex)\r
365     {}\r
366 \r
367   int index = line.indexOf(tag) + tag.length();\r
368   return line.substring(index, line.indexOf("</"));\r
369 \r
370   }\r
371 }\r