Clover icon

Coverage Report

  1. Project Clover database Thu Dec 4 2025 16:11:35 GMT
  2. Package jalview.ws.jws2.jabaws2

File RNAalifoldClient.java

 

Coverage histogram

../../../../img/srcFileCovDistChart1.png
57% of files have more coverage

Code metrics

52
96
10
1
376
263
41
0.43
9.6
10
4.1

Classes

Class Line # Actions
RNAalifoldClient 51 96 41
0.0126582281.3%
 

Contributing tests

This file is covered by 3 tests. .

Source view

1    /*
2    * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3    * Copyright (C) $$Year-Rel$$ The Jalview Authors
4    *
5    * This file is part of Jalview.
6    *
7    * Jalview is free software: you can redistribute it and/or
8    * modify it under the terms of the GNU General Public License
9    * as published by the Free Software Foundation, either version 3
10    * of the License, or (at your option) any later version.
11    *
12    * Jalview is distributed in the hope that it will be useful, but
13    * WITHOUT ANY WARRANTY; without even the implied warranty
14    * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15    * PURPOSE. See the GNU General Public License for more details.
16    *
17    * You should have received a copy of the GNU General Public License
18    * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19    * The Jalview Authors are detailed in the 'AUTHORS' file.
20    */
21    package jalview.ws.jws2.jabaws2;
22   
23    import jalview.api.FeatureColourI;
24    import jalview.datamodel.AlignmentAnnotation;
25    import jalview.datamodel.AlignmentI;
26    import jalview.datamodel.Annotation;
27    import jalview.datamodel.features.FeatureMatcherSetI;
28    import jalview.util.MessageManager;
29    import jalview.ws.uimodel.AlignAnalysisUIText;
30   
31    import java.text.MessageFormat;
32    import java.util.ArrayList;
33    import java.util.LinkedHashMap;
34    import java.util.List;
35    import java.util.Map;
36    import java.util.TreeSet;
37    import java.util.regex.Pattern;
38   
39    import compbio.data.sequence.RNAStructReader.AlifoldResult;
40    import compbio.data.sequence.RNAStructScoreManager;
41    import compbio.data.sequence.Range;
42    import compbio.data.sequence.Score;
43   
44    /**
45    * Client for the JABA RNA Alifold Service
46    *
47    * @author daluke - Daniel Barton
48    *
49    */
50   
 
51    public class RNAalifoldClient extends JabawsAnnotationInstance
52    {
53   
54    // configuration
55   
 
56  0 toggle @Override
57    public String getCalcId()
58    {
59  0 return CALC_ID;
60    }
61   
62    private static String CALC_ID = "jalview.ws.jws2.RNAalifoldClient";
63   
 
64  4 toggle public static AlignAnalysisUIText getAlignAnalysisUIText()
65    {
66  4 return new AlignAnalysisUIText(
67    compbio.ws.client.Services.RNAalifoldWS.toString(),
68    jalview.ws.jws2.jabaws2.RNAalifoldClient.class, CALC_ID, true,
69    false, true, true, false, 2,
70    MessageManager.getString("label.rnalifold_calculations"),
71    MessageManager.getString("tooltip.rnalifold_calculations"),
72    MessageManager.getString("label.rnalifold_settings"),
73    MessageManager.getString("tooltip.rnalifold_settings"));
74    }
75   
 
76  0 toggle public static String getServiceActionText()
77    {
78  0 return "Submitting RNA alignment for Secondary Structure prediction using "
79    + "RNAalifold Service";
80    }
81   
82    // instance
83   
 
84  0 toggle public RNAalifoldClient(Jws2Instance handle)
85    {
86  0 super(handle);
87    }
88   
 
89  0 toggle @Override
90    List<AlignmentAnnotation> annotationFromScoreManager(AlignmentI seqs,
91    Map<String, FeatureColourI> featureColours,
92    Map<String, FeatureMatcherSetI> featureFilters)
93    {
94  0 List<AlignmentAnnotation> ourAnnot = new ArrayList<>();
95   
96    // Unpack the ScoreManager
97  0 List<String> structs = ((RNAStructScoreManager) scoremanager)
98    .getStructs();
99  0 List<TreeSet<Score>> data = ((RNAStructScoreManager) scoremanager)
100    .getData();
101   
102    // test to see if this data object contains base pair contacts
103  0 Score fscore = data.get(0).first();
104  0 boolean bpScores = (fscore.getMethod()
105    .equals(AlifoldResult.contactProbabilities.toString()));
106   
107    // add annotation for the consensus sequence alignment
108  0 createAnnotationRowforScoreHolder(seqs, null,
109    ourAnnot,
110    getCalcId(), structs.get(0), null, null);
111   
112    // Add annotations for the mfe Structure
113  0 createAnnotationRowforScoreHolder(seqs, null,
114    ourAnnot,
115    getCalcId(), structs.get(1), data.get(1), null);
116   
117    // decide whether to add base pair contact probability histogram
118  0 int count = 2;
119  0 if (bpScores)
120    {
121  0 createAnnotationRowforScoreHolder(seqs, null,
122    ourAnnot,
123    getCalcId(), structs.get(2), data.get(0), data.get(2));
124  0 count++;
125    }
126   
127    // Now loop for the rest of the Annotations (if there it isn't stochastic
128    // output
129    // only the centroid and MEA structures remain anyway)
130  0 for (int i = count; i < structs.size(); i++)
131    {
132    // The ensemble values should be displayed in the description of the
133    // first (or all?) Stochastic Backtrack Structures.
134  0 if (!data.get(i).first().getMethod()
135    .equals(AlifoldResult.ensembleValues.toString()))
136    {
137   
138  0 createAnnotationRowforScoreHolder(seqs, null, ourAnnot,
139    getCalcId(), structs.get(i), data.get(i), null);
140    }
141    }
142  0 return ourAnnot;
143    }
144   
 
145  0 toggle private static void createAnnotationRowforScoreHolder(
146    AlignmentI alignment, boolean[] gapMap,
147    List<AlignmentAnnotation> ourAnnot, String calcId, String struct,
148    TreeSet<Score> data, TreeSet<Score> descriptionData)
149    {
150    /*
151    * If contactProbability information is returned from RNAalifold it is
152    * stored in the first TreeSet<Score> object corresponding to the String Id
153    * which holds the consensus alignment. The method enumeration is then
154    * updated to AlifoldResult.contactProbabilties. This line recreates the
155    * same data object as was overwritten with the contact probabilites data.
156    */
157  0 if (data == null)
158    {
159  0 data = compbio.data.sequence.RNAStructReader
160    .newEmptyScore(AlifoldResult.consensusAlignment);
161    }
162   
163  0 if (descriptionData == null)
164    {
165  0 descriptionData = data;
166    }
167   
168  0 String[] typenameAndDescription = constructTypenameAndDescription(
169    descriptionData.first());
170  0 String typename = typenameAndDescription[0];
171  0 String description = typenameAndDescription[1];
172   
173  0 AlignmentAnnotation annotation = alignment
174    .findOrCreateAnnotation(typename, calcId, false, null, null);
175   
176  0 constructAnnotationFromScoreHolder(gapMap, annotation, struct, data);
177   
178    /*
179    * update annotation description with the free Energy, frequency in ensemble
180    * or other data where appropriate.
181    *
182    * Doesnt deal with AlifoldResult.ensembleValues, the free energy of
183    * ensemble and frequency of mfe structure in ensemble. How to deal with
184    * these?
185    */
186  0 annotation.description = description;
187   
188  0 annotation.belowAlignment = false;
189    // annotation.showAllColLabels = true;
190  0 annotation.validateRangeAndDisplay();
191  0 ourAnnot.add(annotation);
192    }
193   
 
194  0 toggle private static AlignmentAnnotation constructAnnotationFromScoreHolder(
195    boolean[] gapMap, AlignmentAnnotation annotation, String struct,
196    TreeSet<Score> data)
197    {
198  0 Annotation[] anns = new Annotation[gapMap != null ? gapMap.length + 1
199    : struct.length()];
200   
201  0 if (data != null && data.size() > 1 && data.first().getMethod()
202    .equals(AlifoldResult.contactProbabilities.toString()))
203    {
204   
205    // The base pair probabilities are stored in a set in scoreholder. we want
206    // a map
207  0 LinkedHashMap<Range, Float> basePairs = new LinkedHashMap<>();
208  0 for (Score score : data)
209    {
210    // The Score objects contain a set of size one containing the range and
211    // an ArrayList<float> of size one containing the probabilty
212  0 basePairs.put(score.getRanges().first(),
213    Float.valueOf(score.getScores().get(0)));
214    }
215   
216  0 for (int i = 0, ri = 0, iEnd = struct.length(); i < iEnd; i++, ri++)
217    {
218  0 if (gapMap != null)
219    {
220    // skip any gapped columns in the input data
221  0 while (!gapMap[ri])
222    {
223  0 ri++;
224    }
225    }
226    // Return all the contacts associated with position i
227  0 LinkedHashMap<Range, Float> contacts = isContact(basePairs, i + 1);
228   
229  0 String description = "";
230  0 float prob = 0f;
231   
232  0 if (contacts.size() == 0)
233    {
234  0 description = "No Data";
235    }
236    else
237    {
238  0 for (Range contact : contacts.keySet())
239    {
240  0 float t = contacts.get(contact);
241  0 if (t > prob)
242    {
243  0 prob = t;
244    }
245  0 description += Integer.toString(contact.from) + "->"
246    + Integer.toString(contact.to) + ": "
247    + Float.toString(t) + "% | ";
248    }
249    }
250   
251  0 anns[ri] = new Annotation(struct.substring(i, i + 1), description,
252    isSS(struct.charAt(i)), prob);
253    }
254    }
255  0 else if (data == null || data.size() == 1)
256    {
257  0 for (int i = 0, ri = 0, iEnd = struct.length(); i < iEnd; i++, ri++)
258    {
259  0 if (gapMap != null)
260    {
261    // skip any gapped columns in the input data
262  0 while (!gapMap[ri] && ri < gapMap.length)
263    {
264  0 ri++;
265    }
266  0 if (ri == gapMap.length)
267    {
268  0 break;
269    }
270    }
271  0 anns[ri] = new Annotation(struct.substring(i, i + 1), "",
272    isSS(struct.charAt(i)), Float.NaN);
273    }
274   
275  0 annotation.graph = 0; // No graph
276    }
277   
278  0 annotation.annotations = anns;
279   
280  0 return annotation;
281    }
282   
 
283  0 toggle private static String[] constructTypenameAndDescription(Score score)
284    {
285  0 String description = "";
286  0 String typename = "";
287  0 String datatype = score.getMethod();
288   
289    // Look up java switch syntax and use one here
290  0 if (datatype.equals(AlifoldResult.mfeStructure.toString()))
291    {
292   
293  0 description = MessageFormat.format(
294    "Minimum Free Energy Structure. Energy: {0} = {1} + {2}",
295    score.getScores().get(0), score.getScores().get(1),
296    score.getScores().get(2));
297  0 typename = "MFE Structure";
298    }
299  0 else if (datatype
300    .equals(AlifoldResult.contactProbabilityStructure.toString()))
301    {
302  0 description = MessageFormat.format("Base Pair Contact Probabilities. "
303    + "Energy of Ensemble: {0} Frequency of Ensemble: {1}",
304    score.getScores().get(0), score.getScores().get(1));
305  0 typename = "Contact Probabilities";
306    }
307  0 else if (datatype.equals(AlifoldResult.centroidStructure.toString()))
308    {
309  0 description = MessageFormat.format(
310    "Centroid Structure. Energy: {0} = {1} + {2}",
311    score.getScores().get(0), score.getScores().get(1),
312    score.getScores().get(2));
313  0 typename = "Centroid Structure";
314    }
315  0 else if (datatype.equals(AlifoldResult.stochBTStructure.toString()))
316    {
317  0 if (score.getScores().size() > 0)
318    {
319  0 description = MessageFormat.format("Probability: {0} Energy: {1}",
320    score.getScores().get(0), score.getScores().get(1));
321    }
322    else
323    {
324  0 description = "Stochastic Backtrack Structure";
325    }
326    }
327  0 else if (datatype.equals(AlifoldResult.MEAStucture.toString()))
328    {
329  0 description = MessageFormat.format(
330    "Maximum Expected Accuracy Values: '{' {0} MEA={1} '}",
331    score.getScores().get(0), score.getScores().get(1));
332  0 typename = "MEA Structure";
333    }
334  0 else if (datatype.equals(AlifoldResult.consensusAlignment.toString()))
335    {
336  0 typename = "RNAalifold Consensus";
337  0 description = "Consensus Alignment Produced by RNAalifold";
338    }
339    else
340    {
341  0 typename = datatype;
342  0 description = typename;
343    }
344   
345  0 return new String[] { typename, description };
346    }
347   
348    // Check whether, at position i there is a base contact and return all the
349    // contacts at this position. Should be in order of descending probability.
 
350  0 toggle private static LinkedHashMap<Range, Float> isContact(
351    LinkedHashMap<Range, Float> basePairs, int i)
352    {
353  0 LinkedHashMap<Range, Float> contacts = new LinkedHashMap<>();
354   
355  0 for (Range contact : basePairs.keySet())
356    {
357    // finds the contacts associtated with position i ordered by the natural
358    // ordering of the Scores TreeSet in ScoreManager which is, descending
359    // probability
360  0 if (contact.from == i || contact.to == i)
361    {
362  0 contacts.put(contact, basePairs.get(contact));
363    }
364    }
365   
366  0 return contacts;
367    }
368   
 
369  0 toggle private static char isSS(char chr)
370    {
371  0 String regex = "\\(|\\)|\\{|\\}|\\[|\\]";
372  0 char ss = (Pattern.matches(regex, Character.toString(chr))) ? 'S' : ' ';
373  0 return ss;
374    }
375   
376    }