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