New class for fetching sequence features
[jalview.git] / src / jalview / analysis / SequenceFeatureFetcher.java
1 package jalview.analysis;\r
2 \r
3 import java.io.*;\r
4 import java.util.*;\r
5 import jalview.io.*;\r
6 import jalview.gui.*;\r
7 import jalview.datamodel.*;\r
8 \r
9 public class SequenceFeatureFetcher implements Runnable\r
10 {\r
11   AlignmentI align;\r
12   AlignmentPanel ap;\r
13 \r
14   public SequenceFeatureFetcher(AlignmentI align, AlignmentPanel ap)\r
15   {\r
16     this.align = align;\r
17     this.ap = ap;\r
18     Thread thread = new Thread(this);\r
19     thread.start();\r
20   }\r
21 \r
22   public void run()\r
23 {\r
24 \r
25   String cache = jalview.bin.Cache.getProperty("UNIPROT_CACHE");\r
26 \r
27   RandomAccessFile out = null;\r
28 \r
29   try{\r
30     if (cache == null)\r
31     {\r
32       jalview.bin.Cache.setProperty("UNIPROT_CACHE", System.getProperty("user.home/uniprot.xml"));\r
33     }\r
34 \r
35 \r
36 \r
37     File test = new File(cache);\r
38     if( !test.exists() )\r
39     {\r
40       out = new RandomAccessFile(cache, "rw");\r
41       out.writeBytes("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");\r
42       out.writeBytes("<UNIPROT_CACHE>\n");\r
43     }\r
44     else\r
45     {\r
46       out = new RandomAccessFile(cache, "rw");\r
47       // open exisiting cache and remove </UNIPROT_CACHE> from the end\r
48       long lastLine = 0;\r
49       String data;\r
50       while ( (data = out.readLine()) != null)\r
51       {\r
52         if (data.indexOf("</entry>") > -1)\r
53           lastLine = out.getFilePointer();\r
54 \r
55       }\r
56       out.seek(lastLine);\r
57     }\r
58 \r
59     int seqIndex = 0;\r
60     Vector sequences = align.getSequences();\r
61 \r
62     while (seqIndex < sequences.size())\r
63     {\r
64       ArrayList ids = new ArrayList();\r
65       for (int i = 0; seqIndex < sequences.size() && i < 50; seqIndex++, i++)\r
66       {\r
67         SequenceI sequence = (SequenceI) sequences.get(seqIndex);\r
68         ids.add(sequence.getName());\r
69       }\r
70 \r
71       tryLocalCacheFirst(ids, align);\r
72 \r
73       if (ids.size() > 0)\r
74       {\r
75         StringBuffer remainingIds = new StringBuffer("uniprot:");\r
76         for (int i = 0; i < ids.size(); i++)\r
77           remainingIds.append(ids.get(i) + ";");\r
78 \r
79          EBIFetchClient ebi = new EBIFetchClient();\r
80         String[] result = ebi.fetchData(remainingIds.toString(), "xml", null);\r
81 \r
82         if(result!=null)\r
83           ReadUniprotFile(result, out, align);\r
84       }\r
85 \r
86     }\r
87 \r
88     if (out != null)\r
89     {\r
90       out.writeBytes("</UNIPROT_CACHE>\n");\r
91       out.close();\r
92     }\r
93   }catch(Exception ex){ex.printStackTrace();}\r
94 \r
95 \r
96 }\r
97 \r
98 void ReadUniprotFile(String [] result, RandomAccessFile out, AlignmentI align)\r
99 {\r
100   SequenceI sequence = null;\r
101   Vector features = null;\r
102   String type, description, status, start, end, pdb = null;\r
103 \r
104 \r
105   for (int r = 0; r < result.length; r++)\r
106   {\r
107     if(sequence==null && result[r].indexOf("<name>")>-1)\r
108     {\r
109       long filePointer = 0;\r
110 \r
111       if(out!=null)\r
112       try{\r
113         filePointer=out.getFilePointer();\r
114         out.writeBytes("<entry>\n");\r
115       }catch(Exception ex){}\r
116 \r
117       sequence = align.findName( parseElement( result[r], "<name>" , out)) ;\r
118       if(sequence==null)\r
119       {\r
120         System.out.println("Couldnt find sequence id. Suggestion is "+result[r]);\r
121 \r
122         // this entry has been suggested by ebi.\r
123         // doesn't match id in alignment file\r
124         try   { out.setLength(filePointer);  }  catch (Exception ex) {}\r
125         // now skip to next entry\r
126         while( result[r].indexOf("</entry>")==-1)\r
127           r++;\r
128       }\r
129 \r
130       features = new Vector();\r
131       type=""; start="0"; end="0"; description=""; status=""; pdb="";\r
132 \r
133     }\r
134 \r
135     if(sequence==null)\r
136       continue;\r
137 \r
138      if( result[r].indexOf("<property type=\"pdb accession\"")>-1)\r
139      {\r
140        pdb = parseValue( result[r], "value=" , out);\r
141        sequence.setPDBId(pdb);\r
142      }\r
143 \r
144      if(result[r].indexOf("feature type")>-1)\r
145      {\r
146        type = parseValue( result[r], "type=" , out);\r
147        description = parseValue( result[r], "description=" , null );\r
148        status = parseValue ( result[r], "status=", null);\r
149 \r
150        while( result[r].indexOf("position")==-1)\r
151        {\r
152            r++;  //<location>\r
153        }\r
154       // r++;\r
155        if(result[r].indexOf("begin")>-1)\r
156        {\r
157          start = parseValue( result[r], "position=" , out);\r
158          end = parseValue( result[++r], "position=" , out);\r
159        }\r
160        else\r
161        {\r
162          start = parseValue( result[r], "position=" , out);\r
163          end = parseValue(   result[r], "position=" , null);\r
164        }\r
165        int sstart = Integer.parseInt(start);\r
166        int eend = Integer.parseInt(end);\r
167        if(out!=null)\r
168          try{ out.writeBytes("</feature>\n"); }catch(Exception ex){}\r
169 \r
170 \r
171        if(sstart>=sequence.getStart() && eend<=sequence.getEnd())\r
172        {\r
173          SequenceFeature sf = new SequenceFeature(type,\r
174              sstart,\r
175              eend,\r
176              description,\r
177              status);\r
178          features.add(sf);\r
179        }\r
180      }\r
181 \r
182      if(result[r].indexOf("</entry>")>-1)\r
183      {\r
184        if(features!=null)\r
185          sequence.setSequenceFeatures( features );\r
186        features = null;\r
187        sequence = null;\r
188        if(out!=null)\r
189          try{  out.writeBytes("</entry>\n"); }catch(Exception ex){}\r
190 \r
191      }\r
192   }\r
193 \r
194   ap.RefreshPanels();\r
195 \r
196 }\r
197 \r
198 void tryLocalCacheFirst(ArrayList ids, AlignmentI align)\r
199 {\r
200   ArrayList cacheData = new ArrayList();\r
201   try{\r
202     BufferedReader in = new BufferedReader(\r
203           new FileReader(jalview.bin.Cache.getProperty("UNIPROT_CACHE")));\r
204 \r
205     // read through cache file, if the cache has sequences we're looking for\r
206     // add the lines to a new String array, Readthis new array and\r
207     // make sure we remove the ids from the list to retrieve from EBI\r
208     String data;\r
209     while( ( data=in.readLine())!=null)\r
210     {\r
211       if(data.indexOf("name")>-1)\r
212       {\r
213         String name = parseElement( data, "<name>" , null) ;\r
214         if(ids.contains( name ) )\r
215         {\r
216           cacheData.add("<entry>");\r
217           cacheData.add(data);\r
218           while( data.indexOf("</entry>")==-1)\r
219           {\r
220             data = in.readLine();\r
221             cacheData.add(data);\r
222           }\r
223           cacheData.add(data);\r
224 \r
225           ids.remove( name );\r
226         }\r
227       }\r
228     }\r
229   }\r
230   catch(Exception ex){ex.printStackTrace();}\r
231 \r
232   String [] localData = new String[cacheData.size()];\r
233   cacheData.toArray( localData );\r
234   if(localData!=null && localData.length>0)\r
235     ReadUniprotFile(localData, null, align);\r
236 }\r
237 \r
238 \r
239 String parseValue(String line, String tag, RandomAccessFile out)\r
240 {\r
241   if(out!=null)\r
242     try{  out.writeBytes(line+"\n"); }catch(Exception ex){}\r
243 \r
244 \r
245   int index = line.indexOf(tag)+tag.length()+1;\r
246   if(index==tag.length())\r
247     return "";\r
248 \r
249   return line.substring( index, line.indexOf("\"", index+1) );\r
250 }\r
251 \r
252 \r
253 String parseElement(String line, String tag, RandomAccessFile out)\r
254 {\r
255   if (out != null)\r
256     try\r
257     {\r
258       out.writeBytes(line + "\n");\r
259     }\r
260     catch (Exception ex)\r
261     {}\r
262 \r
263   int index = line.indexOf(tag) + tag.length();\r
264   return line.substring(index, line.indexOf("</"));\r
265 }\r
266 \r
267 \r
268 }\r