1 package jalview.ws.jws2;
3 import jalview.api.AlignCalcWorkerI;
4 import jalview.datamodel.AlignmentAnnotation;
5 import jalview.datamodel.Annotation;
6 import jalview.gui.AlignFrame;
7 import jalview.ws.jws2.dm.AAConSettings;
8 import jalview.ws.jws2.jabaws2.Jws2Instance;
9 import jalview.ws.params.WsParamSetI;
11 import java.text.MessageFormat;
12 import java.util.ArrayList;
13 import java.util.LinkedHashMap;
14 import java.util.List;
15 import java.util.TreeSet;
16 import java.util.regex.Pattern;
18 import compbio.data.sequence.RNAStructReader.AlifoldResult;
19 import compbio.data.sequence.RNAStructScoreManager;
20 import compbio.data.sequence.Range;
21 import compbio.data.sequence.Score;
22 import compbio.metadata.Argument;
24 public class RNAalifoldClient extends JabawsAlignCalcWorker implements
32 // keeps track of whether the RNAalifold result includes base contact
36 public RNAalifoldClient(Jws2Instance sh, AlignFrame alignFrame,
37 WsParamSetI preset, List<Argument> paramset)
39 super(sh, alignFrame, preset, paramset);
41 if (arguments == null)
42 arguments = new ArrayList<Argument>();
45 methodName = sh.serviceType;
47 nucleotidesAllowed = true;
48 proteinAllowed = false;
52 protected void initViewportParams()
54 ((jalview.gui.AlignViewport) alignViewport).setCalcIdSettingsFor(
56 new AAConSettings(true, service, this.preset,
57 (arguments != null) ? JabaParamStore
58 .getJwsArgsfromJaba(arguments) : null), true);
62 public String getServiceActionText()
64 return "Submitting RNA alignment for Secondary Structure prediction using "
65 + "RNAalifold Service";
69 public void updateResultAnnotation(boolean immediate)
72 if (immediate || !calcMan.isWorking(this) && scoremanager != null)
75 List<AlignmentAnnotation> ourAnnot = new ArrayList<AlignmentAnnotation>();
77 // Unpack the ScoreManager
78 List<String> structs = ((RNAStructScoreManager) scoremanager)
80 List<TreeSet<Score>> data = ((RNAStructScoreManager) scoremanager)
83 // test to see if this data object contains base pair contacts
84 Score fscore = data.get(0).first();
85 this.bpScores = (fscore.getMethod()
86 .equals(AlifoldResult.contactProbabilities.toString()));
88 // add annotation for the consensus sequence alignment
89 createAnnotationRowforScoreHolder(ourAnnot, getCalcId(),
90 structs.get(0), null, null);
92 // Add annotations for the mfe Structure
93 createAnnotationRowforScoreHolder(ourAnnot, getCalcId(),
94 structs.get(1), data.get(1), null);
96 // decide whether to add base pair contact probability histogram
100 createAnnotationRowforScoreHolder(ourAnnot, getCalcId(),
101 structs.get(2), data.get(0), data.get(2));
105 // Now loop for the rest of the Annotations (if there it isn't stochastic
107 // only the centroid and MEA structures remain anyway)
108 for (int i = count; i < structs.size(); i++)
110 // The ensemble values should be displayed in the description of the
111 // first (or all?) Stochastic Backtrack Structures.
112 if (!data.get(i).first().getMethod()
113 .equals(AlifoldResult.ensembleValues.toString()))
116 createAnnotationRowforScoreHolder(ourAnnot, getCalcId(),
117 structs.get(i), data.get(i), null);
121 if (ourAnnot.size() > 0)
124 updateOurAnnots(ourAnnot);
125 ap.adjustAnnotationHeight();
130 protected void createAnnotationRowforScoreHolder(
131 List<AlignmentAnnotation> ourAnnot, String calcId, String struct,
132 TreeSet<Score> data, TreeSet<Score> descriptionData)
135 * If contactProbability information is returned from RNAalifold it is
136 * stored in the first TreeSet<Score> object corresponding to the String Id
137 * which holds the consensus alignment. The method enumeration is then
138 * updated to AlifoldResult.contactProbabilties. This line recreates the
139 * same data object as was overwritten with the contact probabilites data.
142 data = compbio.data.sequence.RNAStructReader
143 .newEmptyScore(AlifoldResult.consensusAlignment);
145 if (descriptionData == null)
146 descriptionData = data;
148 String[] typenameAndDescription = constructTypenameAndDescription(descriptionData
150 String typename = typenameAndDescription[0];
151 String description = typenameAndDescription[1];
153 AlignmentAnnotation annotation = alignViewport.getAlignment()
154 .findOrCreateAnnotation(typename, calcId, false, null, null);
156 constructAnnotationFromScoreHolder(annotation, struct, data);
159 * update annotation description with the free Energy, frequency in ensemble
160 * or other data where appropriate.
162 * Doesnt deal with AlifoldResult.ensembleValues, the free energy of
163 * ensemble and frequency of mfe structure in ensemble. How to deal with
166 annotation.description = description;
168 annotation.belowAlignment = false;
169 // annotation.showAllColLabels = true;
171 alignViewport.getAlignment().validateAnnotation(annotation);
172 af.setMenusForViewport();
174 ourAnnot.add(annotation);
177 private AlignmentAnnotation constructAnnotationFromScoreHolder(
178 AlignmentAnnotation annotation, String struct, TreeSet<Score> data)
180 Annotation[] anns = new Annotation[struct.length()];
184 && data.first().getMethod()
185 .equals(AlifoldResult.contactProbabilities.toString()))
188 // The base pair probabilities are stored in a set in scoreholder. we want
190 LinkedHashMap<Range, Float> basePairs = new LinkedHashMap<Range, Float>();
191 for (Score score : data)
193 // The Score objects contain a set of size one containing the range and
194 // an ArrayList<float> of size one containing the probabilty
195 basePairs.put(score.getRanges().first(), new Float(score
196 .getScores().get(0)));
198 for (int i = 0; i < struct.length(); i++)
201 // Return all the contacts associated with position i
202 LinkedHashMap<Range, Float> contacts = isContact(basePairs, i + 1);
204 String description = "";
207 if (contacts.size() == 0)
209 description = "No Data";
213 for (Range contact : contacts.keySet())
215 float t = contacts.get(contact);
218 description += Integer.toString(contact.from) + "->"
219 + Integer.toString(contact.to) + ": "
220 + Float.toString(t) + "% | ";
224 anns[i] = new Annotation(struct.substring(i, i + 1), description,
225 isSS(struct.charAt(i)), prob);
228 else if (data == null || data.size() == 1)
230 for (int i = 0; i < struct.length(); i++)
233 anns[i] = new Annotation(struct.substring(i, i + 1), "",
234 isSS(struct.charAt(i)), Float.NaN);
237 annotation.graph = 0; // No graph
240 annotation.annotations = anns;
245 private String[] constructTypenameAndDescription(Score score)
247 String description = "";
248 String typename = "";
249 String datatype = score.getMethod();
251 // Look up java switch syntax and use one here
252 if (datatype.equals(AlifoldResult.mfeStructure.toString()))
255 description = MessageFormat.format(
256 "Minimum Free Energy Structure. Energy: {0} = {1} + {2}",
257 score.getScores().get(0), score.getScores().get(1), score
258 .getScores().get(2));
259 typename = "MFE Structure";
261 else if (datatype.equals(AlifoldResult.contactProbabilityStructure
264 description = MessageFormat
265 .format("Base Pair Contact Probabilities. "
266 + "Energy of Ensemble: {0} Frequency of Ensemble: {1}",
267 score.getScores().get(0), score.getScores().get(1));
268 typename = "Contact Probabilities";
270 else if (datatype.equals(AlifoldResult.centroidStructure.toString()))
272 description = MessageFormat.format(
273 "Centroid Structure. Energy: {0} = {1} + {2}", score
274 .getScores().get(0), score.getScores().get(1), score
275 .getScores().get(2));
276 typename = "Centroid Structure";
278 else if (datatype.equals(AlifoldResult.stochBTStructure.toString()))
280 if (score.getScores().size() > 0)
282 description = MessageFormat.format("Probability: {0} Energy: {1}",
283 score.getScores().get(0), score.getScores().get(1));
286 description = "Stochastic Backtrack Structure";
288 else if (datatype.equals(AlifoldResult.MEAStucture.toString()))
290 description = MessageFormat.format(
291 "Maximum Expected Accuracy Values: '{' {0} MEA={1} '}", score
292 .getScores().get(0), score.getScores().get(1));
293 typename = "MEA Structure";
295 else if (datatype.equals(AlifoldResult.consensusAlignment.toString()))
297 typename = "RNAalifold Consensus";
298 description = "Consensus Alignment Produced by RNAalifold";
303 description = typename;
307 { typename, description };
310 // Check whether, at position i there is a base contact and return all the
311 // contacts at this position. Should be in order of descending probability.
312 private LinkedHashMap<Range, Float> isContact(
313 LinkedHashMap<Range, Float> basePairs, int i)
315 LinkedHashMap<Range, Float> contacts = new LinkedHashMap<Range, Float>();
317 for (Range contact : basePairs.keySet())
319 // finds the contacts associtated with position i ordered by the natural
320 // ordering of the Scores TreeSet in ScoreManager which is, descending
322 if (contact.from == i || contact.to == i)
323 contacts.put(contact, basePairs.get(contact));
329 private char isSS(char chr)
331 String regex = "\\(|\\)|\\{|\\}|\\[|\\]";
332 char ss = (Pattern.matches(regex, Character.toString(chr))) ? 'S' : ' ';
336 public String getCalcId()
338 return SequenceAnnotationWSClient.AAConCalcId;