X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fws%2Fjws2%2FRNAalifoldClient.java;h=9ca6d2efcda7a900e502b6bfe6c159d89d56327d;hb=37de9310bec3501cbc6381e0c3dcb282fcaad812;hp=7cd423083ddc4ff26fc103cfe49cb554add601e3;hpb=2efd78f2ea2ca9cb61b259fbb22d6d125db7fd4c;p=jalview.git diff --git a/src/jalview/ws/jws2/RNAalifoldClient.java b/src/jalview/ws/jws2/RNAalifoldClient.java index 7cd4230..9ca6d2e 100644 --- a/src/jalview/ws/jws2/RNAalifoldClient.java +++ b/src/jalview/ws/jws2/RNAalifoldClient.java @@ -1,12 +1,32 @@ +/* + * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$) + * Copyright (C) $$Year-Rel$$ The Jalview Authors + * + * This file is part of Jalview. + * + * Jalview is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 + * of the License, or (at your option) any later version. + * + * Jalview is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Jalview. If not, see . + * The Jalview Authors are detailed in the 'AUTHORS' file. + */ package jalview.ws.jws2; -import jalview.api.AlignCalcWorkerI; import jalview.datamodel.AlignmentAnnotation; import jalview.datamodel.Annotation; import jalview.gui.AlignFrame; -import jalview.ws.jws2.dm.AAConSettings; +import jalview.util.MessageManager; import jalview.ws.jws2.jabaws2.Jws2Instance; import jalview.ws.params.WsParamSetI; +import jalview.ws.uimodel.AlignAnalysisUIText; import java.text.MessageFormat; import java.util.ArrayList; @@ -15,286 +35,370 @@ import java.util.List; import java.util.TreeSet; import java.util.regex.Pattern; +import compbio.data.sequence.FastaSequence; import compbio.data.sequence.RNAStructReader.AlifoldResult; import compbio.data.sequence.RNAStructScoreManager; import compbio.data.sequence.Range; import compbio.data.sequence.Score; import compbio.metadata.Argument; -public class RNAalifoldClient extends JabawsAlignCalcWorker implements - AlignCalcWorkerI +/** + * Client for the JABA RNA Alifold Service + * + * @author daluke - Daniel Barton + * + */ + +public class RNAalifoldClient extends JabawsCalcWorker { - - String methodName; - - AlignFrame af; - - // keeps track of whether the RNAalifold result includes base contact probabilities - boolean bpScores; - - public RNAalifoldClient(Jws2Instance sh, AlignFrame alignFrame, - WsParamSetI preset, List paramset) - { - super(sh, alignFrame, preset, paramset); - - if (arguments == null) arguments = new ArrayList(); - - - af = alignFrame; - methodName = sh.serviceType; - - nucleotidesAllowed = true; - proteinAllowed = false; - initViewportParams(); + + String methodName; + + AlignFrame af; + + // keeps track of whether the RNAalifold result includes base contact + // probabilities + boolean bpScores; + + public RNAalifoldClient(Jws2Instance sh, AlignFrame alignFrame, + WsParamSetI preset, List paramset) + { + super(sh, alignFrame, preset, paramset); + af = alignFrame; + methodName = sh.serviceType; + alignedSeqs = true; + submitGaps = true; + nucleotidesAllowed = true; + proteinAllowed = false; + initViewportParams(); } - protected void initViewportParams() + @Override + public String getCalcId() { - ((jalview.gui.AlignViewport) alignViewport).setCalcIdSettingsFor( - getCalcId(), - new AAConSettings(true, service, this.preset, - (arguments != null) ? JabaParamStore - .getJwsArgsfromJaba(arguments) : null), true); + return CALC_ID; } - - @Override - public String getServiceActionText() - { - return "Submitting RNA alignment for Secondary Structure prediction using " - + "RNAalifold Service"; - } - - - @Override - public void updateResultAnnotation(boolean immediate) - { - - if (immediate || !calcMan.isWorking(this) && scoremanager != null) - { - - List ourAnnot = new ArrayList(); - - // Unpack the ScoreManager - List structs = ((RNAStructScoreManager) scoremanager).getStructs(); - List> data = ((RNAStructScoreManager) scoremanager).getData(); - - // test to see if this data object contains base pair contacts - Score fscore = data.get(0).first(); - this.bpScores = (fscore.getMethod().equals( - AlifoldResult.contactProbabilities.toString())); - - // add annotation for the consensus sequence alignment - createAnnotationRowforScoreHolder(ourAnnot, getCalcId(), structs.get(0), - null, null); - - // Add annotations for the mfe Structure - createAnnotationRowforScoreHolder(ourAnnot, getCalcId(), structs.get(1), - data.get(1), null); - - // decide whether to add base pair contact probability histogram - int count = 2; - if (bpScores) { - createAnnotationRowforScoreHolder(ourAnnot, getCalcId(), structs.get(2), - data.get(0), data.get(2)); - count++; - } - - - // Now loop for the rest of the Annotations (if there it isn't stochastic output - // only the centroid and MEA structures remain anyway) - for (int i = count; i < structs.size(); i++) { - // The ensemble values should be displayed in the description of the - // first (or all?) Stochastic Backtrack Structures. - if (!data.get(i).first().getMethod().equals( - AlifoldResult.ensembleValues.toString())) { - - createAnnotationRowforScoreHolder(ourAnnot, getCalcId(), structs.get(i), - data.get(i), null); - } - } - - if (ourAnnot.size() > 0) { - - updateOurAnnots(ourAnnot); - ap.adjustAnnotationHeight(); - } - } - } - - protected void createAnnotationRowforScoreHolder( - List ourAnnot, String calcId, - String struct, TreeSet data, TreeSet descriptionData) - { - /* If contactProbability information is returned from RNAalifold it is stored - * in the first TreeSet object corresponding to the String Id which - * holds the consensus alignment. The method enumeration is then updated to - * AlifoldResult.contactProbabilties. This line recreates the same - * data object as was overwritten with the contact probabilites data. - */ - if (data == null) data = compbio.data.sequence.RNAStructReader - .newEmptyScore(AlifoldResult.consensusAlignment); - - if (descriptionData == null) descriptionData = data; - - String[] typenameAndDescription = constructTypenameAndDescription( - descriptionData.first()); - String typename = typenameAndDescription[0]; - String description = typenameAndDescription[1]; - - - AlignmentAnnotation annotation = alignViewport.getAlignment() - .findOrCreateAnnotation(typename, calcId, false, null, null); - - constructAnnotationFromScoreHolder(annotation, struct, data); - - /* update annotation description with the free Energy, frequency in ensemble - * or other data where appropriate. - * - * Doesnt deal with AlifoldResult.ensembleValues, the free energy of ensemble - * and frequency of mfe structure in ensemble. How to deal with these? - */ - annotation.description = description; - - annotation.belowAlignment = false; -// annotation.showAllColLabels = true; - - alignViewport.getAlignment().validateAnnotation(annotation); - af.setMenusForViewport(); - - ourAnnot.add(annotation); - } - - - - private AlignmentAnnotation constructAnnotationFromScoreHolder( - AlignmentAnnotation annotation, String struct, TreeSet data) - { - Annotation[] anns = new Annotation[struct.length()]; - - if (data != null && data.size() > 1 && data.first().getMethod().equals( - AlifoldResult.contactProbabilities.toString())) - { - - // The base pair probabilities are stored in a set in scoreholder. we want a map - LinkedHashMap basePairs = new LinkedHashMap(); - for (Score score : data) { - // The Score objects contain a set of size one containing the range and - // an ArrayList of size one containing the probabilty - basePairs.put(score.getRanges().first(), new Float(score.getScores().get(0))); - } - for (int i = 0; i < struct.length(); i++) { - - // Return all the contacts associated with position i - LinkedHashMap contacts = isContact(basePairs, i+1); - - String description = ""; - float prob = 0f; - - if (contacts.size() == 0) { - description = "No Data"; - } - else { - for (Range contact : contacts.keySet()) { - float t = contacts.get(contact); - if (t > prob) prob = t; - description += Integer.toString(contact.from) + "->" - + Integer.toString(contact.to) + ": " + Float.toString(t) + "% | "; - } - } - - anns[i] = new Annotation(struct.substring(i, i+1), description, - isSS(struct.charAt(i)), prob); - } - } - else if (data == null || data.size() == 1) { - for (int i = 0; i < struct.length(); i++) { - - anns[i] = new Annotation(struct.substring(i, i+1), "", - isSS(struct.charAt(i)), Float.NaN); - } - - annotation.graph = 0; // No graph - } - - annotation.annotations = anns; - - return annotation; - } - - private String[] constructTypenameAndDescription(Score score) { - String description = ""; - String typename = ""; - String datatype = score.getMethod(); - - - // Look up java switch syntax and use one here - if (datatype.equals(AlifoldResult.mfeStructure.toString())) { - - description = MessageFormat.format("Minimum Free Energy Structure. Energy: {0} = {1} + {2}", - score.getScores().get(0), score.getScores().get(1), score.getScores().get(2)); - typename = "MFE Structure"; - } - else if (datatype.equals(AlifoldResult.contactProbabilityStructure.toString())) { - description = MessageFormat.format("Base Pair Contact Probabilities. " - + "Energy of Ensemble: {0} Frequency of Ensemble: {1}", - score.getScores().get(0), score.getScores().get(1)); - typename = "Contact Probabilities"; - } - else if (datatype.equals(AlifoldResult.centroidStructure.toString())) { - description = MessageFormat.format("Centroid Structure. Energy: {0} = {1} + {2}", - score.getScores().get(0), score.getScores().get(1), score.getScores().get(2)); - typename = "Centroid Structure"; - } - else if (datatype.equals(AlifoldResult.stochBTStructure.toString())) { - if (score.getScores().size() > 0) { - description = MessageFormat.format("Probability: {0} Energy: {1}", - score.getScores().get(0), score.getScores().get(1)); - } - else description = "Stochastic Backtrack Structure"; - } - else if (datatype.equals(AlifoldResult.MEAStucture.toString())) { - description = MessageFormat.format("Maximum Expected Accuracy Values: '{' {0} MEA={1} '}", - score.getScores().get(0), score.getScores().get(1)); - typename = "MEA Structure"; - } - else if (datatype.equals(AlifoldResult.consensusAlignment.toString())) { - typename = "RNAalifold Consensus"; - description = "Consensus Alignment Produced by RNAalifold"; - } - else { - typename = datatype; - description = typename; - } - - return new String[] {typename, description}; - } - - // Check whether, at position i there is a base contact and return all the - // contacts at this position. Should be in order of descending probability. - private LinkedHashMap isContact(LinkedHashMap basePairs, int i) - { - LinkedHashMap contacts = new LinkedHashMap(); - - for (Range contact : basePairs.keySet()) { - // finds the contacts associtated with position i ordered by the natural - // ordering of the Scores TreeSet in ScoreManager which is, descending probability - if (contact.from == i || contact.to == i) - contacts.put(contact, basePairs.get(contact)); - } - - return contacts; - } - - private char isSS (char chr) { - String regex = "\\(|\\)|\\{|\\}|\\[|\\]"; - char ss = (Pattern.matches(regex, Character.toString(chr))) ? 'S': ' '; - return ss; - } - - public String getCalcId() + + private static String CALC_ID = "jalview.ws.jws2.RNAalifoldClient"; + + public static AlignAnalysisUIText getAlignAnalysisUITest() + { + return new AlignAnalysisUIText( + compbio.ws.client.Services.RNAalifoldWS.toString(), + jalview.ws.jws2.RNAalifoldClient.class, CALC_ID, true, false, + true, MessageManager.getString("label.rnalifold_calculations"), + MessageManager.getString("tooltip.rnalifold_calculations"), + MessageManager.getString("label.rnalifold_settings"), + MessageManager.getString("tooltip.rnalifold_settings")); + } + + @Override + public String getServiceActionText() + { + return "Submitting RNA alignment for Secondary Structure prediction using " + + "RNAalifold Service"; + } + + @Override + boolean checkValidInputSeqs(boolean dynamic, List seqs) + { + return (seqs.size() > 1); + } + + @Override + public void updateResultAnnotation(boolean immediate) + { + + if (immediate || !calcMan.isWorking(this) && scoremanager != null) + { + + List ourAnnot = new ArrayList(); + + // Unpack the ScoreManager + List structs = ((RNAStructScoreManager) scoremanager) + .getStructs(); + List> data = ((RNAStructScoreManager) scoremanager) + .getData(); + + // test to see if this data object contains base pair contacts + Score fscore = data.get(0).first(); + this.bpScores = (fscore.getMethod() + .equals(AlifoldResult.contactProbabilities.toString())); + + // add annotation for the consensus sequence alignment + createAnnotationRowforScoreHolder(ourAnnot, getCalcId(), + structs.get(0), null, null); + + // Add annotations for the mfe Structure + createAnnotationRowforScoreHolder(ourAnnot, getCalcId(), + structs.get(1), data.get(1), null); + + // decide whether to add base pair contact probability histogram + int count = 2; + if (bpScores) + { + createAnnotationRowforScoreHolder(ourAnnot, getCalcId(), + structs.get(2), data.get(0), data.get(2)); + count++; + } + + // Now loop for the rest of the Annotations (if there it isn't stochastic + // output + // only the centroid and MEA structures remain anyway) + for (int i = count; i < structs.size(); i++) + { + // The ensemble values should be displayed in the description of the + // first (or all?) Stochastic Backtrack Structures. + if (!data.get(i).first().getMethod() + .equals(AlifoldResult.ensembleValues.toString())) + { + + createAnnotationRowforScoreHolder(ourAnnot, getCalcId(), + structs.get(i), data.get(i), null); + } + } + + if (ourAnnot.size() > 0) + { + + updateOurAnnots(ourAnnot); + ap.adjustAnnotationHeight(); + } + } + } + + protected void createAnnotationRowforScoreHolder( + List ourAnnot, String calcId, String struct, + TreeSet data, TreeSet descriptionData) + { + /* + * If contactProbability information is returned from RNAalifold it is + * stored in the first TreeSet object corresponding to the String Id + * which holds the consensus alignment. The method enumeration is then + * updated to AlifoldResult.contactProbabilties. This line recreates the + * same data object as was overwritten with the contact probabilites data. + */ + if (data == null) + { + data = compbio.data.sequence.RNAStructReader + .newEmptyScore(AlifoldResult.consensusAlignment); + } + + if (descriptionData == null) + { + descriptionData = data; + } + + String[] typenameAndDescription = constructTypenameAndDescription(descriptionData + .first()); + String typename = typenameAndDescription[0]; + String description = typenameAndDescription[1]; + + AlignmentAnnotation annotation = alignViewport.getAlignment() + .findOrCreateAnnotation(typename, calcId, false, null, null); + + constructAnnotationFromScoreHolder(annotation, struct, data); + + /* + * update annotation description with the free Energy, frequency in ensemble + * or other data where appropriate. + * + * Doesnt deal with AlifoldResult.ensembleValues, the free energy of + * ensemble and frequency of mfe structure in ensemble. How to deal with + * these? + */ + annotation.description = description; + + annotation.belowAlignment = false; + // annotation.showAllColLabels = true; + + alignViewport.getAlignment().validateAnnotation(annotation); + af.setMenusForViewport(); + + ourAnnot.add(annotation); + } + + private AlignmentAnnotation constructAnnotationFromScoreHolder( + AlignmentAnnotation annotation, String struct, TreeSet data) + { + Annotation[] anns = new Annotation[gapMap != null ? gapMap.length + 1 + : struct.length()]; + + if (data != null + && data.size() > 1 + && data.first().getMethod() + .equals(AlifoldResult.contactProbabilities.toString())) + { + + // The base pair probabilities are stored in a set in scoreholder. we want + // a map + LinkedHashMap basePairs = new LinkedHashMap(); + for (Score score : data) + { + // The Score objects contain a set of size one containing the range and + // an ArrayList of size one containing the probabilty + basePairs.put(score.getRanges().first(), new Float(score + .getScores().get(0))); + } + + for (int i = 0, ri = 0, iEnd = struct.length(); i < iEnd; i++, ri++) + { + if (gapMap != null) + { + // skip any gapped columns in the input data + while (!gapMap[ri]) + { + ri++; + } + } + // Return all the contacts associated with position i + LinkedHashMap contacts = isContact(basePairs, i + 1); + + String description = ""; + float prob = 0f; + + if (contacts.size() == 0) + { + description = "No Data"; + } + else + { + for (Range contact : contacts.keySet()) + { + float t = contacts.get(contact); + if (t > prob) + { + prob = t; + } + description += Integer.toString(contact.from) + "->" + + Integer.toString(contact.to) + ": " + + Float.toString(t) + "% | "; + } + } + + anns[ri] = new Annotation(struct.substring(i, i + 1), description, + isSS(struct.charAt(i)), prob); + } + } + else if (data == null || data.size() == 1) + { + for (int i = 0, ri = 0, iEnd = struct.length(); i < iEnd; i++, ri++) + { + if (gapMap != null) + { + // skip any gapped columns in the input data + while (!gapMap[ri] && ri < gapMap.length) + { + ri++; + } + if (ri == gapMap.length) + { + break; + } + } + anns[ri] = new Annotation(struct.substring(i, i + 1), "", + isSS(struct.charAt(i)), Float.NaN); + } + + annotation.graph = 0; // No graph + } + + annotation.annotations = anns; + + return annotation; + } + + private String[] constructTypenameAndDescription(Score score) + { + String description = ""; + String typename = ""; + String datatype = score.getMethod(); + + // Look up java switch syntax and use one here + if (datatype.equals(AlifoldResult.mfeStructure.toString())) + { + + description = MessageFormat.format( + "Minimum Free Energy Structure. Energy: {0} = {1} + {2}", + score.getScores().get(0), score.getScores().get(1), score + .getScores().get(2)); + typename = "MFE Structure"; + } + else if (datatype.equals(AlifoldResult.contactProbabilityStructure + .toString())) + { + description = MessageFormat + .format("Base Pair Contact Probabilities. " + + "Energy of Ensemble: {0} Frequency of Ensemble: {1}", + score.getScores().get(0), score.getScores().get(1)); + typename = "Contact Probabilities"; + } + else if (datatype.equals(AlifoldResult.centroidStructure.toString())) + { + description = MessageFormat.format( + "Centroid Structure. Energy: {0} = {1} + {2}", score + .getScores().get(0), score.getScores().get(1), score + .getScores().get(2)); + typename = "Centroid Structure"; + } + else if (datatype.equals(AlifoldResult.stochBTStructure.toString())) + { + if (score.getScores().size() > 0) + { + description = MessageFormat.format("Probability: {0} Energy: {1}", + score.getScores().get(0), score.getScores().get(1)); + } + else + { + description = "Stochastic Backtrack Structure"; + } + } + else if (datatype.equals(AlifoldResult.MEAStucture.toString())) + { + description = MessageFormat.format( + "Maximum Expected Accuracy Values: '{' {0} MEA={1} '}", score + .getScores().get(0), score.getScores().get(1)); + typename = "MEA Structure"; + } + else if (datatype.equals(AlifoldResult.consensusAlignment.toString())) + { + typename = "RNAalifold Consensus"; + description = "Consensus Alignment Produced by RNAalifold"; + } + else + { + typename = datatype; + description = typename; + } + + return new String[] { typename, description }; + } + + // Check whether, at position i there is a base contact and return all the + // contacts at this position. Should be in order of descending probability. + private LinkedHashMap isContact( + LinkedHashMap basePairs, int i) + { + LinkedHashMap contacts = new LinkedHashMap(); + + for (Range contact : basePairs.keySet()) + { + // finds the contacts associtated with position i ordered by the natural + // ordering of the Scores TreeSet in ScoreManager which is, descending + // probability + if (contact.from == i || contact.to == i) + { + contacts.put(contact, basePairs.get(contact)); + } + } + + return contacts; + } + + private char isSS(char chr) { - return SequenceAnnotationWSClient.AAConCalcId; + String regex = "\\(|\\)|\\{|\\}|\\[|\\]"; + char ss = (Pattern.matches(regex, Character.toString(chr))) ? 'S' : ' '; + return ss; } - }