package jalview.ws.ebi; import jalview.datamodel.AlignmentAnnotation; import jalview.datamodel.AlignmentI; import jalview.datamodel.Annotation; import jalview.datamodel.SequenceFeature; import jalview.datamodel.SequenceGroup; import jalview.datamodel.SequenceI; import jalview.io.FileParse; import jalview.viewmodel.AlignmentViewport; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; public class HmmerJSONProcessor { /** * result to be annotated. may not be null */ AlignmentI resultAl; /** * viewport on the alignment. may be null at construction time */ AlignmentViewport viewAl = null; public HmmerJSONProcessor(AlignmentI searchResult) { resultAl = searchResult; } public void parseFrom(FileParse jsonsource) throws IOException, OutOfMemoryError { JSONParser hmmerResultParser = new JSONParser(); Object jsonResults = null; try { jsonResults = hmmerResultParser.parse(jsonsource.getReader()); } catch (Exception p) { throw new IOException("While parsing from " + jsonsource.getInFile(), p); } if (jsonResults == null) { throw new IOException("No data at" + jsonsource.getInFile()); } if (!(jsonResults instanceof JSONObject)) { throw new IOException("Unexpected JSON model at " + jsonsource.getInFile()); } try { JSONObject hmmsearchr = (JSONObject) ((JSONObject) jsonResults) .get("results"); // now process the hits addStatistics((JSONObject) hmmsearchr.get("stats")); JSONArray jsonArray = (JSONArray) hmmsearchr.get("hits"); long p = 1; for (Object hit : jsonArray) { JSONObject hmmhit = (JSONObject) hit; addHit(hmmhit, p++); } } catch (ClassCastException q) { throw new IOException("Unexpected JSON model content at " + jsonsource.getInFile(), q); } } /** * * @param object * - actually a JSONObject key value set of search statistics. */ public void addStatistics(JSONObject stats) { for (Object stat : stats.keySet()) { String key = (String) stat; Object val = stats.get(key); resultAl.setProperty(key, "" + val); } } // encodings for JSON keys /** * score becomes sequence associated AlignmentAnnotation */ private String[] score = { "aliId", "ali_IdCount", "bitscore", "ievalue", "aliSim", "aliSimCount", "aliL", "aliSim", "ievalue", "cevalue" }; /** * attrib becomes numeric or binary attribute for sequence with respect to * this hmmsearch run */ private String[] attrib = { "bias", "oasc", "is_included", "is_reported" }; /** * name of the hmmsearch query */ private String[] label = { "alihmmname" // (query label?)}, }; /** * integer attributes for each */ private String[] ipos = { "alihmmfrom", "alihmmto" }, pos_l = { "alimline", "alimodel", "alirfline" }; /** * positional quantitative annotation encoded as strings. */ private String[] pos_nscore = { "alippline" }; // // mapping of keys to types of property on sequence // public void addHit(JSONObject hmmrhit, long p) { String sname = (String) hmmrhit.get("name"); SequenceI[] hits = resultAl.findSequenceMatch(sname); if (hits == null) { System.err.println("No seq for " + sname); } double pvalue = (Double) hmmrhit.get("pvalue"); double evalue = Double.valueOf("" + hmmrhit.get("evalue")); for (Object domainhit : ((JSONArray) hmmrhit.get("domains"))) { JSONObject dhit = (JSONObject) domainhit; // dhit.get(key) // alihmmfrom,alihmmto alimodel long alihmmfrom = (long) dhit.get("alihmmfrom"), alihmmto = (long) dhit .get("alihmmto"), alisqfrom = (long) dhit.get("alisqfrom"), alisqto = (long) dhit .get("alisqto"); // alisqfrom,alisqto,aliaseq // alippline String aliaseq = (String) dhit.get("aliaseq"), alimodel = (String) dhit .get("alimodel"), ppline = (String) dhit.get("alippline"); // int found = 0; SequenceI firsthit = null; for (SequenceI hitseq : hits) { // match alisqfrom,alisqto,seq if (hitseq.getStart() == alisqfrom && hitseq.getEnd() == alisqto) { if (found == 0) { firsthit = hitseq; } found++; // annotated a sequence AlignmentAnnotation alipp = parsePosteriorProb(ppline); AlignmentAnnotation pval = new AlignmentAnnotation("p-value", "hmmer3 pvalue", pvalue); AlignmentAnnotation eval = new AlignmentAnnotation("e-value", "hmmer3 evalue", evalue); pval.setCalcId("HMMER3"); eval.setCalcId("HMMER3"); alipp.setCalcId("HMMER3"); hitseq.addAlignmentAnnotation(pval); hitseq.addAlignmentAnnotation(eval); alipp.createSequenceMapping(hitseq, hitseq.getStart(), false); hitseq.addAlignmentAnnotation(alipp); String arch; hitseq.addSequenceFeature(new SequenceFeature( "Pfam Domain Architecture", (hmmrhit.get("archindex")) + " " + (arch = (String) hmmrhit.get("arch")), 0, 0, (hmmrhit.get("archScore") != null ? Integer .valueOf((String) hmmrhit.get("archScore")) : 0f), "HMMER3")); addArchGroup(hitseq, arch); alipp.setScore(Double.valueOf("" + dhit.get("bitscore"))); alipp.adjustForAlignment(); resultAl.addAnnotation(pval); resultAl.addAnnotation(eval); resultAl.addAnnotation(alipp); alipp.validateRangeAndDisplay(); } } // look for other sequences represented by this hit and create rep groups // could be in "pdbs", or .. addRedundantSeqGroup(firsthit, alisqfrom, alisqto, (JSONArray) hmmrhit.get("seqs"), true); } } /** * series of operations to perform for the viewpanel associated with the * alignment */ private List viewOps = new ArrayList(); public void updateView(AlignmentViewport view) { viewAl = view; for (Runnable op : viewOps) { op.run(); } } private void addRedundantSeqGroup(final SequenceI firsthit, long alisqfrom, long alisqto, JSONArray others, boolean justDelete) { if (others != null) { final SequenceGroup repgroup = new SequenceGroup(); repgroup.setSeqrep(firsthit); repgroup.addOrRemove(firsthit, false); repgroup.setStartRes(0); repgroup.setEndRes(resultAl.getWidth() - 1); for (Object otherseq : others.toArray(new JSONObject[0])) { String repseq = (String) ((JSONObject) otherseq).get("dn"); SequenceI[] other = resultAl.findSequenceMatch(repseq); if (other != null && other.length > 0) { if (justDelete) { for (SequenceI oth : other) { resultAl.deleteSequence(oth); } ; } else { int ofound = 0; for (SequenceI oth : other) { if (oth.getStart() == alisqfrom && oth.getEnd() == alisqto) { ofound++; repgroup.addSequence(oth, false); } } if (ofound == 0) { System.err.println("Warn - no match for redundant hit " + repseq + "/" + alisqfrom + "-" + alisqto); } if (ofound > 1) { System.err .println("Warn - multiple matches for redundant hit " + repseq + "/" + alisqfrom + "-" + alisqto); } } } } if (repgroup.getSequences().size() > 1) { // queue a hide operation final HmmerJSONProcessor me = this; viewOps.add(new Runnable() { @Override public void run() { me.viewAl.hideRepSequences(firsthit, repgroup); } }); } } } Map groups = new HashMap(); private void addArchGroup(SequenceI seqToAdd, String groupNam) { SequenceGroup sg = groups.get(groupNam); if (sg == null) { sg = new SequenceGroup(); sg.setName(groupNam); sg.addSequence(seqToAdd, false); sg.setStartRes(0); sg.setEndRes(resultAl.getWidth() - 1); groups.put(groupNam, sg); resultAl.addGroup(sg); } else { sg.addSequence(seqToAdd, false); } } private AlignmentAnnotation parsePosteriorProb(String ppline) { Annotation[] ae = new Annotation[ppline.length()]; int spos = 0; for (int i = 0, iSize = ppline.length(); i < iSize; i++) { char pp = ppline.charAt(i); if (pp == '*') { ae[spos++] = new Annotation(10f); } else { if (pp >= '0' && pp <= '9') { ae[spos++] = new Annotation(Integer.valueOf("" + pp)); } } } AlignmentAnnotation pprob = new AlignmentAnnotation( "Posterior Probability", "Likelihood of HMM fit at each hit position.", ae); pprob.graph = AlignmentAnnotation.BAR_GRAPH; pprob.visible = false; return pprob; } }