JAL-3829 update for v1.0 3d-beacons api spec
[jalview.git] / src / jalview / gui / structurechooser / TDBResultAnalyser.java
1 package jalview.gui.structurechooser;
2
3 import java.util.ArrayList;
4 import java.util.Arrays;
5 import java.util.BitSet;
6 import java.util.Collection;
7 import java.util.Collections;
8 import java.util.Comparator;
9 import java.util.List;
10
11 import jalview.datamodel.SequenceI;
12 import jalview.fts.api.FTSData;
13 import jalview.fts.core.FTSRestRequest;
14
15 public class TDBResultAnalyser
16 {
17
18   /**
19    * model categories - update as needed. warnings output if unknown types
20    * encountered.
21    * 
22    * Order denotes 'trust'
23    */
24   private static List<String> EXP_CATEGORIES = Arrays
25           .asList(new String[]
26           { "EXPERIMENTALLY DETERMINED", "DEEP-LEARNING",
27               "TEMPLATE-BASED" });
28
29   private SequenceI seq;
30
31   private Collection<FTSData> collectedResults;
32
33   private FTSRestRequest lastTdbRequest;
34
35   private int idx_ups;
36
37   private int idx_upe;
38
39   private int idx_mcat;
40
41   private int idx_mqual;
42
43   private int idx_resol;
44
45   public TDBResultAnalyser(SequenceI seq,
46           Collection<FTSData> collectedResults,
47           FTSRestRequest lastTdbRequest)
48   {
49     this.seq = seq;
50     this.collectedResults = collectedResults;
51     this.lastTdbRequest = lastTdbRequest;
52     idx_ups = lastTdbRequest.getFieldIndex("Uniprot Start");
53     idx_upe = lastTdbRequest.getFieldIndex("Uniprot End");
54     idx_mcat = lastTdbRequest.getFieldIndex("Model Category");
55     idx_mqual = lastTdbRequest.getFieldIndex("Confidence");
56     idx_resol = lastTdbRequest.getFieldIndex("Resolution");
57   }
58   private final int scoreCategory(String cat)
59   {
60     // TODO: make quicker
61     int idx = EXP_CATEGORIES.indexOf(cat.toUpperCase());
62     if (idx == -1)
63     {
64       System.out.println("Unknown category: '" + cat + "'");
65     }
66     return -EXP_CATEGORIES.size() - idx;
67   }
68
69   /**
70    * sorts records discovered by 3D beacons and excludes any that don't
71    * intersect with the sequence's start/end rage
72    * 
73    * @return
74    */
75   public List<FTSData> getFilteredResponse()
76   {
77     List<FTSData> filteredResponse = new ArrayList<FTSData>();
78
79     // ignore anything outside the sequence region
80     for (FTSData row : collectedResults)
81     {
82       int up_s = (Integer) row.getSummaryData()[idx_ups];
83       int up_e = (Integer) row.getSummaryData()[idx_upe];
84
85       if (seq == row.getSummaryData()[0] && up_e > seq.getStart()
86               && up_s < seq.getEnd())
87       {
88         filteredResponse.add(row);
89       }
90     }
91     // sort according to decreasing length,
92     // increasing start
93     Collections.sort(filteredResponse, new Comparator<FTSData>()
94     {
95
96
97       @Override
98       public int compare(FTSData o1, FTSData o2)
99       {
100         Object[] o1data = o1.getSummaryData();
101         Object[] o2data = o2.getSummaryData();
102         int o1_s = (Integer) o1data[idx_ups];
103         int o1_e = (Integer) o1data[idx_upe];
104         int o1_cat = scoreCategory((String) o1data[idx_mcat]);
105         int o2_s = (Integer) o2data[idx_ups];
106         int o2_e = (Integer) o2data[idx_upe];
107         int o2_cat = scoreCategory((String) o2data[idx_mcat]);
108
109         if (o1_cat == o2_cat)
110         {
111           if (o1_s == o2_s)
112           {
113             int o1_xtent = o1_e - o1_s;
114             int o2_xtent = o2_e - o2_s;
115             if (o1_xtent == o2_xtent)
116             {
117               if (o1_cat == scoreCategory(EXP_CATEGORIES.get(0)))
118               {
119                 // experimental structures, so rank on quality
120                 double o1_res = (Double) o1data[idx_resol];
121                 double o2_res = (Double) o2data[idx_resol];
122                 return (o2_res < o1_res) ? 1 : (o2_res == o1_res) ? 0 : -1;
123               }
124               else
125               {
126                 // models, so rank on qmean
127                 float o1_mq = (Float) o1data[idx_mqual];
128                 float o2_mq = (Float) o2data[idx_mqual];
129                 return (o2_mq < o1_mq) ? 1 : (o2_mq == o1_mq) ? 0 : -1;
130               }
131             }
132             else
133             {
134               return o1_xtent - o2_xtent;
135             }
136           }
137           else
138           {
139             return o1_s - o2_s;
140           }
141         }
142         else
143         {
144           return o2_cat - o1_cat;
145         }
146       }
147
148       @Override
149       public boolean equals(Object obj)
150       {
151         return super.equals(obj);
152       }
153     });
154     return filteredResponse;
155   }
156
157   /**
158    * return list of structures to be marked as selected for this sequence according to given criteria
159    * @param filteredStructures - sorted, filtered structures from getFilteredResponse
160    * 
161    */
162   public List<FTSData> selectStructures(List<FTSData> filteredStructures)
163   {
164     List<FTSData> selected = new ArrayList<FTSData>();
165     BitSet cover = new BitSet();
166     cover.set(seq.getStart(),seq.getEnd());
167     // walk down the list of structures, selecting some to add to selected
168     for (FTSData structure:filteredStructures)
169     {
170       Object[] odata=structure.getSummaryData();
171       int o1_s = (Integer) odata[idx_ups];
172       int o1_e = (Integer) odata[idx_upe];
173       int o1_cat = scoreCategory((String) odata[idx_mcat]);
174       BitSet scover = new BitSet();
175       // measure intersection
176       scover.set(o1_s,o1_e);
177       scover.and(cover);
178       if (scover.cardinality()>4)
179       {
180         selected.add(structure);
181         // clear the range covered by this structure
182         cover.andNot(scover); 
183       }
184     }
185     // final step is to sort on length - this might help the superposition process
186     Collections.sort(selected,new Comparator<FTSData>()
187     {
188       @Override
189       public int compare(FTSData o1, FTSData o2)
190       {
191         Object[] o1data = o1.getSummaryData();
192         Object[] o2data = o2.getSummaryData();
193         int o1_xt = ((Integer) o1data[idx_upe]) - ((Integer) o1data[idx_ups]);
194         int o1_cat = scoreCategory((String) o1data[idx_mcat]);
195         int o2_xt = ((Integer) o2data[idx_upe]-(Integer) o2data[idx_ups]);
196         int o2_cat = scoreCategory((String) o2data[idx_mcat]);
197         return o2_xt-o1_xt;
198       }
199     });
200     return selected;
201   }
202
203 }