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;
25 * Client for the JABA RNA Alifold Service
26 * @author daluke - Daniel Barton
30 public class RNAalifoldClient extends JabawsAlignCalcWorker implements
38 // keeps track of whether the RNAalifold result includes base contact
42 public RNAalifoldClient(Jws2Instance sh, AlignFrame alignFrame,
43 WsParamSetI preset, List<Argument> paramset)
45 super(sh, alignFrame, preset, paramset);
47 //if (arguments == null)
48 // arguments = new ArrayList<Argument>();
51 methodName = sh.serviceType;
54 nucleotidesAllowed = true;
55 proteinAllowed = false;
59 public String getCalcId()
63 private static String CALC_ID="jalview.ws.jws2.RNAalifoldClient";
69 public String getServiceActionText()
71 return "Submitting RNA alignment for Secondary Structure prediction using "
72 + "RNAalifold Service";
76 public void updateResultAnnotation(boolean immediate)
79 if (immediate || !calcMan.isWorking(this) && scoremanager != null)
82 List<AlignmentAnnotation> ourAnnot = new ArrayList<AlignmentAnnotation>();
84 // Unpack the ScoreManager
85 List<String> structs = ((RNAStructScoreManager) scoremanager)
87 List<TreeSet<Score>> data = ((RNAStructScoreManager) scoremanager)
90 // test to see if this data object contains base pair contacts
91 Score fscore = data.get(0).first();
92 this.bpScores = (fscore.getMethod()
93 .equals(AlifoldResult.contactProbabilities.toString()));
95 // add annotation for the consensus sequence alignment
96 createAnnotationRowforScoreHolder(ourAnnot, getCalcId(),
97 structs.get(0), null, null);
99 // Add annotations for the mfe Structure
100 createAnnotationRowforScoreHolder(ourAnnot, getCalcId(),
101 structs.get(1), data.get(1), null);
103 // decide whether to add base pair contact probability histogram
107 createAnnotationRowforScoreHolder(ourAnnot, getCalcId(),
108 structs.get(2), data.get(0), data.get(2));
112 // Now loop for the rest of the Annotations (if there it isn't stochastic
114 // only the centroid and MEA structures remain anyway)
115 for (int i = count; i < structs.size(); i++)
117 // The ensemble values should be displayed in the description of the
118 // first (or all?) Stochastic Backtrack Structures.
119 if (!data.get(i).first().getMethod()
120 .equals(AlifoldResult.ensembleValues.toString()))
123 createAnnotationRowforScoreHolder(ourAnnot, getCalcId(),
124 structs.get(i), data.get(i), null);
128 if (ourAnnot.size() > 0)
131 updateOurAnnots(ourAnnot);
132 ap.adjustAnnotationHeight();
137 protected void createAnnotationRowforScoreHolder(
138 List<AlignmentAnnotation> ourAnnot, String calcId, String struct,
139 TreeSet<Score> data, TreeSet<Score> descriptionData)
142 * If contactProbability information is returned from RNAalifold it is
143 * stored in the first TreeSet<Score> object corresponding to the String Id
144 * which holds the consensus alignment. The method enumeration is then
145 * updated to AlifoldResult.contactProbabilties. This line recreates the
146 * same data object as was overwritten with the contact probabilites data.
149 data = compbio.data.sequence.RNAStructReader
150 .newEmptyScore(AlifoldResult.consensusAlignment);
152 if (descriptionData == null)
153 descriptionData = data;
155 String[] typenameAndDescription = constructTypenameAndDescription(descriptionData
157 String typename = typenameAndDescription[0];
158 String description = typenameAndDescription[1];
160 AlignmentAnnotation annotation = alignViewport.getAlignment()
161 .findOrCreateAnnotation(typename, calcId, false, null, null);
163 constructAnnotationFromScoreHolder(annotation, struct, data);
166 * update annotation description with the free Energy, frequency in ensemble
167 * or other data where appropriate.
169 * Doesnt deal with AlifoldResult.ensembleValues, the free energy of
170 * ensemble and frequency of mfe structure in ensemble. How to deal with
173 annotation.description = description;
175 annotation.belowAlignment = false;
176 // annotation.showAllColLabels = true;
178 alignViewport.getAlignment().validateAnnotation(annotation);
179 af.setMenusForViewport();
181 ourAnnot.add(annotation);
184 private AlignmentAnnotation constructAnnotationFromScoreHolder(
185 AlignmentAnnotation annotation, String struct, TreeSet<Score> data)
187 Annotation[] anns = new Annotation[struct.length()];
191 && data.first().getMethod()
192 .equals(AlifoldResult.contactProbabilities.toString()))
195 // The base pair probabilities are stored in a set in scoreholder. we want
197 LinkedHashMap<Range, Float> basePairs = new LinkedHashMap<Range, Float>();
198 for (Score score : data)
200 // The Score objects contain a set of size one containing the range and
201 // an ArrayList<float> of size one containing the probabilty
202 basePairs.put(score.getRanges().first(), new Float(score
203 .getScores().get(0)));
205 for (int i = 0; i < struct.length(); i++)
208 // Return all the contacts associated with position i
209 LinkedHashMap<Range, Float> contacts = isContact(basePairs, i + 1);
211 String description = "";
214 if (contacts.size() == 0)
216 description = "No Data";
220 for (Range contact : contacts.keySet())
222 float t = contacts.get(contact);
225 description += Integer.toString(contact.from) + "->"
226 + Integer.toString(contact.to) + ": "
227 + Float.toString(t) + "% | ";
231 anns[i] = new Annotation(struct.substring(i, i + 1), description,
232 isSS(struct.charAt(i)), prob);
235 else if (data == null || data.size() == 1)
237 for (int i = 0; i < struct.length(); i++)
240 anns[i] = new Annotation(struct.substring(i, i + 1), "",
241 isSS(struct.charAt(i)), Float.NaN);
244 annotation.graph = 0; // No graph
247 annotation.annotations = anns;
252 private String[] constructTypenameAndDescription(Score score)
254 String description = "";
255 String typename = "";
256 String datatype = score.getMethod();
258 // Look up java switch syntax and use one here
259 if (datatype.equals(AlifoldResult.mfeStructure.toString()))
262 description = MessageFormat.format(
263 "Minimum Free Energy Structure. Energy: {0} = {1} + {2}",
264 score.getScores().get(0), score.getScores().get(1), score
265 .getScores().get(2));
266 typename = "MFE Structure";
268 else if (datatype.equals(AlifoldResult.contactProbabilityStructure
271 description = MessageFormat
272 .format("Base Pair Contact Probabilities. "
273 + "Energy of Ensemble: {0} Frequency of Ensemble: {1}",
274 score.getScores().get(0), score.getScores().get(1));
275 typename = "Contact Probabilities";
277 else if (datatype.equals(AlifoldResult.centroidStructure.toString()))
279 description = MessageFormat.format(
280 "Centroid Structure. Energy: {0} = {1} + {2}", score
281 .getScores().get(0), score.getScores().get(1), score
282 .getScores().get(2));
283 typename = "Centroid Structure";
285 else if (datatype.equals(AlifoldResult.stochBTStructure.toString()))
287 if (score.getScores().size() > 0)
289 description = MessageFormat.format("Probability: {0} Energy: {1}",
290 score.getScores().get(0), score.getScores().get(1));
293 description = "Stochastic Backtrack Structure";
295 else if (datatype.equals(AlifoldResult.MEAStucture.toString()))
297 description = MessageFormat.format(
298 "Maximum Expected Accuracy Values: '{' {0} MEA={1} '}", score
299 .getScores().get(0), score.getScores().get(1));
300 typename = "MEA Structure";
302 else if (datatype.equals(AlifoldResult.consensusAlignment.toString()))
304 typename = "RNAalifold Consensus";
305 description = "Consensus Alignment Produced by RNAalifold";
310 description = typename;
314 { typename, description };
317 // Check whether, at position i there is a base contact and return all the
318 // contacts at this position. Should be in order of descending probability.
319 private LinkedHashMap<Range, Float> isContact(
320 LinkedHashMap<Range, Float> basePairs, int i)
322 LinkedHashMap<Range, Float> contacts = new LinkedHashMap<Range, Float>();
324 for (Range contact : basePairs.keySet())
326 // finds the contacts associtated with position i ordered by the natural
327 // ordering of the Scores TreeSet in ScoreManager which is, descending
329 if (contact.from == i || contact.to == i)
330 contacts.put(contact, basePairs.get(contact));
336 private char isSS(char chr)
338 String regex = "\\(|\\)|\\{|\\}|\\[|\\]";
339 char ss = (Pattern.matches(regex, Character.toString(chr))) ? 'S' : ' ';