Clover icon

Coverage Report

  1. Project Clover database Mon Sep 2 2024 17:57:51 BST
  2. Package jalview.gui.structurechooser

File TDBResultAnalyser.java

 

Coverage histogram

../../../img/srcFileCovDistChart8.png
21% of files have more coverage

Code metrics

64
105
9
1
347
247
46
0.44
11.67
9
5.11

Classes

Class Line # Actions
TDBResultAnalyser 36 105 46
0.7808988778.1%
 

Contributing tests

This file is covered by 6 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.gui.structurechooser;
22   
23    import java.util.ArrayList;
24    import java.util.Arrays;
25    import java.util.BitSet;
26    import java.util.Collection;
27    import java.util.Collections;
28    import java.util.Comparator;
29    import java.util.List;
30    import java.util.Locale;
31   
32    import jalview.datamodel.SequenceI;
33    import jalview.fts.api.FTSData;
34    import jalview.fts.core.FTSRestRequest;
35   
 
36    public class TDBResultAnalyser
37    {
38   
39    /**
40    * model categories - update as needed. warnings output if unknown types
41    * encountered.
42    *
43    * Order denotes 'trust'
44    */
45    private static List<String> EXP_CATEGORIES = Arrays
46    .asList(new String[]
47    { "EXPERIMENTALLY DETERMINED", "DEEP-LEARNING", "AB-INITIO",
48    "TEMPLATE-BASED", "CONFORMATIONAL ENSEMBLE" });
49   
50    private SequenceI seq;
51   
52    private Collection<FTSData> collectedResults;
53   
54    private FTSRestRequest lastTdbRequest;
55   
56    private int idx_ups;
57   
58    private int idx_upe;
59   
60    private int idx_mcat;
61   
62    private int idx_mqual;
63   
64    private int idx_mqualtype;
65   
66    private int idx_resol;
67   
68    /**
69    * selection model
70    */
71    private String filter = null;
72   
73    /**
74    * limit to particular source
75    */
76    private String sourceFilter = null;
77   
78    private int idx_mprov;
79   
 
80  7 toggle public TDBResultAnalyser(SequenceI seq,
81    Collection<FTSData> collectedResults,
82    FTSRestRequest lastTdbRequest, String fieldToFilterBy,
83    String string)
84    {
85  7 this.seq = seq;
86  7 this.collectedResults = collectedResults;
87  7 this.lastTdbRequest = lastTdbRequest;
88  7 this.filter = fieldToFilterBy;
89  7 this.sourceFilter = string;
90  7 idx_ups = lastTdbRequest.getFieldIndex("Uniprot Start");
91  7 idx_upe = lastTdbRequest.getFieldIndex("Uniprot End");
92  7 idx_mcat = lastTdbRequest.getFieldIndex("Model Category");
93  7 idx_mprov = lastTdbRequest.getFieldIndex("Provider");
94  7 idx_mqual = lastTdbRequest.getFieldIndex("Confidence");
95  7 idx_resol = lastTdbRequest.getFieldIndex("Resolution");
96  7 idx_mqualtype = lastTdbRequest.getFieldIndex("Confidence Score Type");
97    }
98   
99    /**
100    * maintain and resolve categories to 'trust order' TODO: change the trust
101    * scheme to something comprehensible.
102    *
103    * @param cat
104    * @return 0 for null cat, less than zero for others
105    */
 
106  35592 toggle public final int scoreCategory(String cat)
107    {
108  35592 if (cat == null)
109    {
110  0 return 0;
111    }
112  35592 String upper_cat = cat.toUpperCase(Locale.ROOT);
113  35592 int idx = EXP_CATEGORIES.indexOf(upper_cat);
114  35592 if (idx == -1)
115    {
116  0 jalview.bin.Console.outPrintln("Unknown category: '" + cat + "'");
117  0 EXP_CATEGORIES.add(upper_cat);
118  0 idx = EXP_CATEGORIES.size() - 1;
119    }
120  35592 return -EXP_CATEGORIES.size() - idx;
121    }
122   
123    /**
124    * sorts records discovered by 3D beacons and excludes any that don't
125    * intersect with the sequence's start/end rage
126    *
127    * @return
128    */
 
129  7 toggle public List<FTSData> getFilteredResponse()
130    {
131  7 List<FTSData> filteredResponse = new ArrayList<FTSData>();
132   
133    // ignore anything outside the sequence region
134  7 for (FTSData row : collectedResults)
135    {
136  2553 if (row.getSummaryData() != null
137    && row.getSummaryData()[idx_ups] != null)
138    {
139  2553 int up_s = (Integer) row.getSummaryData()[idx_ups];
140  2553 int up_e = (Integer) row.getSummaryData()[idx_upe];
141  2553 String provider = (String) row.getSummaryData()[idx_mprov];
142  2553 String mcat = (String) row.getSummaryData()[idx_mcat];
143    // this makes sure all new categories are in the score array.
144  2553 int scorecat = scoreCategory(mcat);
145  2553 if (sourceFilter == null || sourceFilter.equals(provider))
146    {
147  2553 if (seq == row.getSummaryData()[0] && up_e > seq.getStart()
148    && up_s < seq.getEnd())
149    {
150  2553 filteredResponse.add(row);
151    }
152    }
153    }
154    }
155    // sort according to decreasing length,
156    // increasing start
157  7 Collections.sort(filteredResponse, new Comparator<FTSData>()
158    {
 
159  12658 toggle @Override
160    public int compare(FTSData o1, FTSData o2)
161    {
162  12658 Object[] o1data = o1.getSummaryData();
163  12658 Object[] o2data = o2.getSummaryData();
164  12658 int o1_s = (Integer) o1data[idx_ups];
165  12658 int o1_e = (Integer) o1data[idx_upe];
166  12658 int o1_cat = scoreCategory((String) o1data[idx_mcat]);
167  12658 String o1_prov = ((String) o1data[idx_mprov])
168    .toUpperCase(Locale.ROOT);
169  12658 int o2_s = (Integer) o2data[idx_ups];
170  12658 int o2_e = (Integer) o2data[idx_upe];
171  12658 int o2_cat = scoreCategory((String) o2data[idx_mcat]);
172  12658 String o2_prov = ((String) o2data[idx_mprov])
173    .toUpperCase(Locale.ROOT);
174  12658 String o1_qualtype = (String) o1data[idx_mqualtype],
175    o2_qualtype = (String) o2data[idx_mqualtype];
176   
177  12658 if (o1_cat == o2_cat)
178    {
179  12477 if (o1_s == o2_s)
180    {
181  6511 int o1_xtent = o1_e - o1_s;
182  6511 int o2_xtent = o2_e - o2_s;
183  6511 if (o1_xtent == o2_xtent)
184    {
185    // EXPERIMENTAL DATA ALWAYS TRUMPS MODELS
186  4942 if (o1_cat == scoreCategory(EXP_CATEGORIES.get(0)))
187    {
188  4870 if (o1_prov.equals(o2_prov))
189    {
190  4870 if ("PDBE".equals(o1_prov))
191    {
192  4870 if (eitherNull(idx_resol, o1data, o2data))
193    {
194  249 return nonNullFirst(idx_resol, o1data, o2data);
195    }
196    // experimental structures, so rank on quality
197  4621 double o1_res = (Double) o1data[idx_resol];
198  4621 double o2_res = (Double) o2data[idx_resol];
199  4621 return (o2_res < o1_res) ? 1
200  1960 : (o2_res == o1_res) ? 0 : -1;
201    }
202    else
203    {
204  0 return 0; // no change in order
205    }
206    }
207    else
208    {
209    // PDBe always ranked above all other experimentally
210    // determined categories
211  0 return "PDBE".equals(o1_prov) ? -1
212  0 : "PDBE".equals(o2_prov) ? 1 : 0;
213    }
214    }
215    else
216    {
217    // RANK ON QUALITY - DOWNRANK THOSE WITH NO QUALITY MEASURE
218  72 if (eitherNull(idx_mqualtype, o1data, o2data))
219    {
220  7 return nonNullFirst(idx_mqualtype, o1data, o2data);
221    }
222    // ONLY COMPARE LIKE QUALITY SCORES
223  65 if (!o1_qualtype.equals(o2_qualtype))
224    {
225    // prefer LDDT measure over others
226  0 return "pLDDT".equals(o1_qualtype) ? -1
227  0 : "pLDDT".equals(o2_qualtype) ? 1 : 0;
228    }
229    // OR NO VALUE FOR THE QUALITY
230  65 if (eitherNull(idx_mqual, o1data, o2data))
231    {
232  0 return nonNullFirst(idx_mqual, o1data, o2data);
233    }
234    // models, so rank on qmean - b
235  65 double o1_mq = (Double) o1data[idx_mqual];
236  65 double o2_mq = (Double) o2data[idx_mqual];
237  65 int res = (o2_mq < o1_mq) ? 1 : (o2_mq == o1_mq) ? 0 : -1;
238  65 return ("pLDDT".equals(o1_qualtype)) ? -res : res;
239    }
240    }
241    else
242    {
243  1569 return o1_xtent - o2_xtent;
244    }
245    }
246    else
247    {
248  5966 return o1_s - o2_s;
249    }
250    }
251    else
252    {
253    // if both are not experimental, then favour alphafold
254  181 if (o2_cat > 0 && o1_cat > 0)
255    {
256  0 return "ALPHAFOLD DB".equals(o1_prov) ? -1
257  0 : "ALPHAFOLD DB".equals(o2_prov) ? 1 : 0;
258    }
259  181 return o2_cat - o1_cat;
260    }
261    }
262   
 
263  256 toggle private int nonNullFirst(int idx_resol, Object[] o1data,
264    Object[] o2data)
265    {
266  256 return o1data[idx_resol] == o2data[idx_resol] ? 0
267  73 : o1data[idx_resol] != null ? -1 : 1;
268    }
269   
 
270  5007 toggle private boolean eitherNull(int idx_resol, Object[] o1data,
271    Object[] o2data)
272    {
273  5007 return (o1data[idx_resol] == null || o2data[idx_resol] == null);
274    }
275   
 
276  0 toggle @Override
277    public boolean equals(Object obj)
278    {
279  0 return super.equals(obj);
280    }
281    });
282  7 return filteredResponse;
283    }
284   
285    /**
286    * return list of structures to be marked as selected for this sequence
287    * according to given criteria
288    *
289    * @param filteredStructures
290    * - sorted, filtered structures from getFilteredResponse
291    *
292    */
 
293  7 toggle public List<FTSData> selectStructures(List<FTSData> filteredStructures)
294    {
295  7 List<FTSData> selected = new ArrayList<FTSData>();
296  7 BitSet cover = new BitSet();
297  7 cover.set(seq.getStart(), seq.getEnd());
298    // walk down the list of structures, selecting some to add to selected
299    // TODO: could do simple DP - double loop to select largest number of
300    // structures covering largest number of sites
301  7 for (FTSData structure : filteredStructures)
302    {
303  2553 Object[] odata = structure.getSummaryData();
304  2553 int o1_s = (Integer) odata[idx_ups];
305  2553 int o1_e = (Integer) odata[idx_upe];
306  2553 int o1_cat = scoreCategory((String) odata[idx_mcat]);
307  2553 BitSet scover = new BitSet();
308    // measure intersection
309  2553 scover.set(o1_s, o1_e);
310  2553 scover.and(cover);
311  2553 if (scover.cardinality() > 4)
312    {
313  46 selected.add(structure);
314    // clear the range covered by this structure
315  46 cover.andNot(scover);
316    }
317    }
318  7 if (selected.size() == 0)
319    {
320  0 return selected;
321    }
322    // final step is to sort on length - this might help the superposition
323    // process
324  7 Collections.sort(selected, new Comparator<FTSData>()
325    {
 
326  114 toggle @Override
327    public int compare(FTSData o1, FTSData o2)
328    {
329  114 Object[] o1data = o1.getSummaryData();
330  114 Object[] o2data = o2.getSummaryData();
331  114 int o1_xt = ((Integer) o1data[idx_upe])
332    - ((Integer) o1data[idx_ups]);
333  114 int o1_cat = scoreCategory((String) o1data[idx_mcat]);
334  114 int o2_xt = ((Integer) o2data[idx_upe] - (Integer) o2data[idx_ups]);
335  114 int o2_cat = scoreCategory((String) o2data[idx_mcat]);
336  114 return o2_xt - o1_xt;
337    }
338    });
339  7 if (filter.equals(
340    ThreeDBStructureChooserQuerySource.FILTER_FIRST_BEST_COVERAGE))
341    {
342  7 return selected.subList(0, 1);
343    }
344  0 return selected;
345    }
346   
347    }