0bf9fdb484d6861143b4da43574dcb33cfa70582
[jalview.git] / src / jalview / gui / structurechooser / ThreeDBStructureChooserQuerySource.java
1 package jalview.gui.structurechooser;
2
3 import java.util.ArrayList;
4 import java.util.Collection;
5 import java.util.HashSet;
6 import java.util.LinkedHashSet;
7 import java.util.List;
8 import java.util.Set;
9
10 import javax.swing.JTable;
11
12 import jalview.datamodel.DBRefEntry;
13 import jalview.datamodel.DBRefSource;
14 import jalview.datamodel.PDBEntry;
15 import jalview.datamodel.SequenceI;
16 import jalview.fts.api.FTSDataColumnI;
17 import jalview.fts.api.FTSRestClientI;
18 import jalview.fts.core.FTSDataColumnPreferences;
19 import jalview.fts.core.FTSDataColumnPreferences.PreferenceSource;
20 import jalview.fts.core.FTSRestRequest;
21 import jalview.fts.core.FTSRestResponse;
22 import jalview.fts.service.threedbeacons.TDBeaconsFTSRestClient;
23 import jalview.jbgui.FilterOption;
24 import jalview.util.MessageManager;
25
26 /**
27  * logic for querying the 3DBeacons API for structures of sequences
28  * 
29  * @author jprocter
30  */
31 public class ThreeDBStructureChooserQuerySource
32         extends StructureChooserQuerySource
33 {
34
35   private static int MAX_QLENGTH = 7820;
36
37   protected FTSRestRequest lastTdbRequest;
38
39   protected FTSRestClientI tdbRestClient;
40
41   public ThreeDBStructureChooserQuerySource()
42   {
43     tdbRestClient = TDBeaconsFTSRestClient.getInstance();
44     docFieldPrefs = new FTSDataColumnPreferences(
45             PreferenceSource.STRUCTURE_CHOOSER,
46             TDBeaconsFTSRestClient.getInstance());
47
48   }
49
50
51   /**
52    * Builds a query string for a given sequences using its DBRef entries
53    * 3d Beacons is only useful for uniprot IDs
54    * @param seq
55    *          the sequences to build a query for
56    * @return the built query string
57    */
58
59   public String buildQuery(SequenceI seq)
60   {
61     boolean isPDBRefsFound = false;
62     boolean isUniProtRefsFound = false;
63     StringBuilder queryBuilder = new StringBuilder();
64     Set<String> seqRefs = new LinkedHashSet<>();
65
66     /*
67      * note PDBs as DBRefEntry so they are not duplicated in query
68      */
69     Set<String> pdbids = new HashSet<>();
70
71     List<DBRefEntry> refs = seq.getDBRefs();
72     if (refs != null && refs.size() != 0)
73     {
74       for (int ib = 0, nb = refs.size(); ib < nb; ib++)
75       {
76         DBRefEntry dbRef = refs.get(ib);
77         if (isValidSeqName(getDBRefId(dbRef))
78                 && queryBuilder.length() < MAX_QLENGTH)
79         {
80           if (dbRef.getSource().equalsIgnoreCase(DBRefSource.UNIPROT) && dbRef.isCanonical())
81           {
82             // TODO: pick best Uniprot accession 
83             isUniProtRefsFound=true;
84             return getDBRefId(dbRef);
85             
86           }
87         }
88       }
89     }
90     return null;
91   }
92
93  
94
95   /**
96    * Ensures sequence ref names are not less than 3 characters and does not
97    * contain a database name
98    * 
99    * @param seqName
100    * @return
101    */
102   static boolean isValidSeqName(String seqName)
103   {
104     // System.out.println("seqName : " + seqName);
105     String ignoreList = "pdb,uniprot,swiss-prot";
106     if (seqName.length() < 3)
107     {
108       return false;
109     }
110     if (seqName.contains(":"))
111     {
112       return false;
113     }
114     seqName = seqName.toLowerCase();
115     for (String ignoredEntry : ignoreList.split(","))
116     {
117       if (seqName.contains(ignoredEntry))
118       {
119         return false;
120       }
121     }
122     return true;
123   }
124
125   static String getDBRefId(DBRefEntry dbRef)
126   {
127     String ref = dbRef.getAccessionId().replaceAll("GO:", "");
128     return ref;
129   }
130
131   /**
132    * FTSRestClient specific query builder to recover associated structure data
133    * records for a sequence
134    * 
135    * @param seq
136    *          - seq to generate a query for
137    * @param wantedFields
138    *          - fields to retrieve
139    * @param selectedFilterOpt
140    *          - criterion for ranking results (e.g. resolution)
141    * @param b
142    *          - sort ascending or descending
143    * @return
144    * @throws Exception
145    */
146   public FTSRestResponse fetchStructuresMetaData(SequenceI seq,
147           Collection<FTSDataColumnI> wantedFields,
148           FilterOption selectedFilterOpt, boolean b) throws Exception
149   {
150     FTSRestResponse resultList;
151     FTSRestRequest tdbRequest = getTDBeaconsRequest(seq, wantedFields);
152     resultList = tdbRestClient.executeRequest(tdbRequest);
153
154     lastTdbRequest = tdbRequest;
155     return resultList;
156   }
157   
158
159   private FTSRestRequest getTDBeaconsRequest(SequenceI seq, Collection<FTSDataColumnI> wantedFields)
160   {
161     FTSRestRequest pdbRequest = new FTSRestRequest();
162     pdbRequest.setAllowEmptySeq(false);
163     pdbRequest.setResponseSize(500);
164     pdbRequest.setWantedFields(wantedFields);
165     String query = buildQuery(seq);
166     if (query==null)  {
167       return null;
168     }
169     pdbRequest.setSearchTerm(query + ".json");
170     pdbRequest.setAssociatedSequence(seq);
171     return pdbRequest;
172   }
173
174 @Override
175   public List<FilterOption> getAvailableFilterOptions(String VIEWS_FILTER)
176   {
177     List<FilterOption> filters = new ArrayList<FilterOption>();
178     filters.add(new FilterOption(
179             MessageManager.getString("label.best_quality"),
180             "overall_quality", VIEWS_FILTER, false));
181     filters.add(new FilterOption(
182             MessageManager.getString("label.best_resolution"),
183             "resolution", VIEWS_FILTER, false));
184     filters.add(new FilterOption(
185             MessageManager.getString("label.most_protein_chain"),
186             "number_of_protein_chains", VIEWS_FILTER, false));
187     filters.add(new FilterOption(
188             MessageManager.getString("label.most_bound_molecules"),
189             "number_of_bound_molecules", VIEWS_FILTER, false));
190     filters.add(new FilterOption(
191             MessageManager.getString("label.most_polymer_residues"),
192             "number_of_polymer_residues", VIEWS_FILTER, true));
193   
194     return filters;
195   }
196   /**
197    * FTSRestClient specific query builder to pick top ranked entry from a
198    * fetchStructuresMetaData query
199    * 
200    * @param seq
201    *          - seq to generate a query for
202    * @param wantedFields
203    *          - fields to retrieve
204    * @param selectedFilterOpt
205    *          - criterion for ranking results (e.g. resolution)
206    * @param b
207    *          - sort ascending or descending
208    * @return
209    * @throws Exception
210    */
211   public FTSRestResponse selectFirstRankedQuery(SequenceI seq,
212           Collection<FTSDataColumnI> wantedFields, String fieldToFilterBy,
213           boolean b) throws Exception
214   {
215
216     FTSRestResponse resultList;
217     FTSRestRequest pdbRequest = getTDBeaconsRequest(seq, wantedFields);
218     if (pdbRequest == null) {
219       return null;
220     }
221     pdbRequest.setResponseSize(1);
222     resultList = tdbRestClient.executeRequest(pdbRequest);
223     
224     // TODO: client side filtering - sort results and pick top one (or N)
225
226     lastTdbRequest = pdbRequest;
227     return resultList;
228   }
229
230   @Override
231   public PDBEntry[] collectSelectedRows(JTable restable, int[] selectedRows,
232           List<SequenceI> selectedSeqsToView)
233   {
234     int refSeqColIndex = restable.getColumn("Ref Sequence")
235             .getModelIndex();
236
237     PDBEntry[] pdbEntriesToView=new PDBEntry[selectedRows.length];
238     int count = 0;
239     int idColumnIndex = restable.getColumn("Model id").getModelIndex();
240     int urlColumnIndex = restable.getColumn("Url").getModelIndex();
241     int typeColumnIndex = restable.getColumn("Provider").getModelIndex();
242     int categoryColumnIndex = restable.getColumn("Model Category").getModelIndex();
243     
244     for (int row : selectedRows)
245     {
246       // unique id - could be a horrible hash
247       
248       String pdbIdStr = restable.getValueAt(row,idColumnIndex)
249               .toString();
250       String urlStr = restable.getValueAt(row,urlColumnIndex)
251               .toString();
252       String typeColumn = restable.getValueAt(row,typeColumnIndex)
253               .toString();
254       SequenceI selectedSeq = (SequenceI) restable.getValueAt(row,
255               refSeqColIndex);
256       selectedSeqsToView.add(selectedSeq);
257       PDBEntry pdbEntry = selectedSeq.getPDBEntry(pdbIdStr);
258       if (pdbEntry == null)
259       {
260         pdbEntry = getFindEntry(pdbIdStr,
261                 selectedSeq.getAllPDBEntries());
262       }
263
264       if (pdbEntry == null)
265       {
266         pdbEntry = new PDBEntry();
267         pdbEntry.setId(pdbIdStr);
268         pdbEntry.setType(PDBEntry.Type.MMCIF);
269         if (!"PDBe".equalsIgnoreCase(typeColumn))
270         {
271           pdbEntry.setRetrievalUrl(urlStr);
272         }
273         selectedSeq.getDatasetSequence().addPDBId(pdbEntry);
274       }
275       pdbEntriesToView[count++] = pdbEntry;
276     }
277     return pdbEntriesToView;
278   }
279
280
281   @Override
282   protected FTSRestRequest getLastFTSRequest()
283   {
284     return lastTdbRequest;
285   }
286 }