d0f3c181e8ef6c71aa748fb3845e8535080a9cbc
[jalview.git] / src / jalview / ws / ebi / HmmerJSONProcessor.java
1 package jalview.ws.ebi;
2
3 import jalview.datamodel.AlignmentAnnotation;
4 import jalview.datamodel.AlignmentI;
5 import jalview.datamodel.Annotation;
6 import jalview.datamodel.SequenceFeature;
7 import jalview.datamodel.SequenceGroup;
8 import jalview.datamodel.SequenceI;
9 import jalview.io.FileParse;
10
11 import java.io.IOException;
12 import java.util.HashMap;
13 import java.util.Map;
14
15 import org.json.simple.JSONArray;
16 import org.json.simple.JSONObject;
17 import org.json.simple.parser.JSONParser;
18
19 public class HmmerJSONProcessor
20 {
21   AlignmentI resultAl;
22
23   public HmmerJSONProcessor(AlignmentI searchResult)
24   {
25     resultAl = searchResult;
26   }
27
28   public void parseFrom(FileParse jsonsource) throws IOException,
29           OutOfMemoryError
30   {
31     JSONParser hmmerResultParser = new JSONParser();
32     Object jsonResults = null;
33     try
34     {
35       jsonResults = hmmerResultParser.parse(jsonsource.getReader());
36     } catch (Exception p)
37     {
38       throw new IOException("While parsing from " + jsonsource.getInFile(),
39               p);
40     }
41     if (jsonResults == null)
42     {
43       throw new IOException("No data at" + jsonsource.getInFile());
44     }
45     if (!(jsonResults instanceof JSONObject))
46     {
47       throw new IOException("Unexpected JSON model at "
48               + jsonsource.getInFile());
49     }
50     try
51     {
52       JSONObject hmmsearchr = (JSONObject) ((JSONObject) jsonResults)
53               .get("results");
54       // now process the hits
55       addStatistics((JSONObject) hmmsearchr.get("stats"));
56       JSONArray jsonArray = (JSONArray) hmmsearchr.get("hits");
57       long p = 1;
58       for (Object hit : jsonArray)
59       {
60         JSONObject hmmhit = (JSONObject) hit;
61         addHit(hmmhit, p++);
62       }
63     } catch (ClassCastException q)
64     {
65       throw new IOException("Unexpected JSON model content at "
66               + jsonsource.getInFile(), q);
67     }
68   }
69
70   /**
71    * 
72    * @param object
73    *          - actually a JSONObject key value set of search statistics.
74    */
75   public void addStatistics(JSONObject stats)
76   {
77     for (Object stat : stats.keySet())
78     {
79       String key = (String) stat;
80       Object val = stats.get(key);
81       resultAl.setProperty(key, "" + val);
82     }
83   }
84
85   // encodings for JSON keys
86   /**
87    * score becomes sequence associated AlignmentAnnotation
88    */
89   private String[] score = { "aliId", "ali_IdCount", "bitscore", "ievalue",
90       "aliSim", "aliSimCount", "aliL", "aliSim", "ievalue", "cevalue" };
91
92   /**
93    * attrib becomes numeric or binary attribute for sequence with respect to
94    * this hmmsearch run
95    */
96   private String[] attrib = { "bias", "oasc", "is_included", "is_reported" };
97
98   /**
99    * name of the hmmsearch query
100    */
101   private String[] label = { "alihmmname" // (query label?)},
102   };
103
104   /**
105    * integer attributes for each
106    */
107   private String[] ipos = { "alihmmfrom", "alihmmto" }, pos_l = {
108       "alimline", "alimodel", "alirfline" };
109
110   /**
111    * positional quantitative annotation encoded as strings.
112    */
113   private String[] pos_nscore = { "alippline" };
114
115   //
116   // mapping of keys to types of property on sequence
117   //
118   public void addHit(JSONObject hmmrhit, long p)
119   {
120     String sname = (String) hmmrhit.get("name");
121     SequenceI[] hits = resultAl.findSequenceMatch(sname);
122     if (hits == null)
123     {
124       System.err.println("No seq for " + sname);
125     }
126     double pvalue = (Double) hmmrhit.get("pvalue");
127
128     double evalue = Double.valueOf("" + hmmrhit.get("evalue"));
129     for (Object domainhit : ((JSONArray) hmmrhit.get("domains")))
130     {
131       JSONObject dhit = (JSONObject) domainhit;
132       // dhit.get(key)
133
134       // alihmmfrom,alihmmto alimodel
135       long alihmmfrom = (long) dhit.get("alihmmfrom"), alihmmto = (long) dhit
136               .get("alihmmto"), alisqfrom = (long) dhit.get("alisqfrom"), alisqto = (long) dhit
137               .get("alisqto");
138
139       // alisqfrom,alisqto,aliaseq
140
141       // alippline
142       String aliaseq = (String) dhit.get("aliaseq"), alimodel = (String) dhit
143               .get("alimodel"), ppline = (String) dhit.get("alippline");
144       //
145       int found = 0;
146       for (SequenceI hitseq : hits)
147       {
148         // match alisqfrom,alisqto,seq
149         if (hitseq.getStart() == alisqfrom && hitseq.getEnd() == alisqto)
150         {
151           found++; // annotated a sequence
152           AlignmentAnnotation alipp = parsePosteriorProb(ppline);
153           AlignmentAnnotation pval = new AlignmentAnnotation("p-value",
154                   "hmmer3 pvalue", pvalue);
155           AlignmentAnnotation eval = new AlignmentAnnotation("e-value",
156                   "hmmer3 evalue", evalue);
157           pval.setCalcId("HMMER3");
158           eval.setCalcId("HMMER3");
159           alipp.setCalcId("HMMER3");
160           hitseq.addAlignmentAnnotation(pval);
161           hitseq.addAlignmentAnnotation(eval);
162           alipp.createSequenceMapping(hitseq, hitseq.getStart(), false);
163           hitseq.addAlignmentAnnotation(alipp);
164           String arch;
165           hitseq.addSequenceFeature(new SequenceFeature(
166                   "Pfam Domain Architecture", (hmmrhit.get("archindex"))
167                           + " " + (arch = (String) hmmrhit.get("arch")), 0,
168                   0, Integer.valueOf((String) hmmrhit.get("archScore")),
169                   "HMMER3"));
170           addArchGroup(hitseq, arch);
171           alipp.setScore(Double.valueOf("" + dhit.get("bitscore")));
172           alipp.adjustForAlignment();
173           resultAl.addAnnotation(pval);
174           resultAl.addAnnotation(eval);
175           resultAl.addAnnotation(alipp);
176           alipp.validateRangeAndDisplay();
177         }
178       }
179       if (found == 0)
180       {
181         System.err.println("Warn - no match for json hit " + sname + "/"
182                 + alisqfrom + "-" + alisqto);
183       }
184       if (found > 1)
185       {
186         System.err.println("Warn - multiple matches for json hit " + sname
187                 + "/" + alisqfrom + "-" + alisqto);
188       }
189       // look for other sequences represented by this hit and create
190     }
191   }
192
193   Map<String, SequenceGroup> groups = new HashMap<String, SequenceGroup>();
194
195   private void addArchGroup(SequenceI seqToAdd, String groupNam)
196   {
197     SequenceGroup sg = groups.get(groupNam);
198     if (sg == null)
199     {
200       sg = new SequenceGroup();
201       sg.setName(groupNam);
202       sg.addSequence(seqToAdd, false);
203       sg.setStartRes(0);
204       sg.setEndRes(resultAl.getWidth() - 1);
205       groups.put(groupNam, sg);
206       resultAl.addGroup(sg);
207     }
208     else
209     {
210       sg.addSequence(seqToAdd, false);
211     }
212   }
213
214   private AlignmentAnnotation parsePosteriorProb(String ppline)
215   {
216     Annotation[] ae = new Annotation[ppline.length()];
217     int spos = 0;
218     for (int i = 0, iSize = ppline.length(); i < iSize; i++)
219     {
220       char pp = ppline.charAt(i);
221       if (pp == '*')
222       {
223         ae[spos++] = new Annotation(10f);
224       }
225       else
226       {
227         if (pp >= '0' && pp <= '9')
228         {
229           ae[spos++] = new Annotation(Integer.valueOf("" + pp));
230         }
231       }
232     }
233     AlignmentAnnotation pprob = new AlignmentAnnotation(
234             "Posterior Probability",
235             "Likelihood of HMM fit at each hit position.", ae);
236     pprob.graph = AlignmentAnnotation.BAR_GRAPH;
237     pprob.visible = false;
238     return pprob;
239   }
240 }