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