1 package jalview.gui.structurechooser;
3 import java.util.ArrayList;
4 import java.util.Arrays;
5 import java.util.Collection;
6 import java.util.Collections;
7 import java.util.Comparator;
8 import java.util.HashSet;
9 import java.util.LinkedHashSet;
10 import java.util.List;
13 import javax.swing.JTable;
15 import jalview.datamodel.DBRefEntry;
16 import jalview.datamodel.DBRefSource;
17 import jalview.datamodel.PDBEntry;
18 import jalview.datamodel.SequenceI;
19 import jalview.fts.api.FTSData;
20 import jalview.fts.api.FTSDataColumnI;
21 import jalview.fts.api.FTSRestClientI;
22 import jalview.fts.core.FTSDataColumnPreferences;
23 import jalview.fts.core.FTSDataColumnPreferences.PreferenceSource;
24 import jalview.fts.core.FTSRestRequest;
25 import jalview.fts.core.FTSRestResponse;
26 import jalview.fts.service.threedbeacons.TDBeaconsFTSRestClient;
27 import jalview.jbgui.FilterOption;
28 import jalview.util.MessageManager;
31 * logic for querying the 3DBeacons API for structures of sequences
35 public class ThreeDBStructureChooserQuerySource
36 extends StructureChooserQuerySource
39 private static int MAX_QLENGTH = 7820;
41 protected FTSRestRequest lastTdbRequest;
43 protected FTSRestClientI tdbRestClient;
45 private FTSRestRequest lastPdbRequest;
47 public ThreeDBStructureChooserQuerySource()
49 tdbRestClient = TDBeaconsFTSRestClient.getInstance();
50 docFieldPrefs = new FTSDataColumnPreferences(
51 PreferenceSource.STRUCTURE_CHOOSER,
52 TDBeaconsFTSRestClient.getInstance());
57 * Builds a query string for a given sequences using its DBRef entries 3d
58 * Beacons is only useful for uniprot IDs
61 * the sequences to build a query for
62 * @return the built query string
65 public String buildQuery(SequenceI seq)
67 boolean isPDBRefsFound = false;
68 boolean isUniProtRefsFound = false;
69 StringBuilder queryBuilder = new StringBuilder();
70 Set<String> seqRefs = new LinkedHashSet<>();
73 * note PDBs as DBRefEntry so they are not duplicated in query
75 Set<String> pdbids = new HashSet<>();
77 List<DBRefEntry> refs = seq.getDBRefs();
78 if (refs != null && refs.size() != 0)
80 for (int ib = 0, nb = refs.size(); ib < nb; ib++)
82 DBRefEntry dbRef = refs.get(ib);
83 if (isValidSeqName(getDBRefId(dbRef))
84 && queryBuilder.length() < MAX_QLENGTH)
86 if (dbRef.getSource().equalsIgnoreCase(DBRefSource.UNIPROT)
87 && dbRef.isCanonical())
89 // TODO: pick best Uniprot accession
90 isUniProtRefsFound = true;
91 return getDBRefId(dbRef);
101 * Ensures sequence ref names are not less than 3 characters and does not
102 * contain a database name
107 static boolean isValidSeqName(String seqName)
109 // System.out.println("seqName : " + seqName);
110 String ignoreList = "pdb,uniprot,swiss-prot";
111 if (seqName.length() < 3)
115 if (seqName.contains(":"))
119 seqName = seqName.toLowerCase();
120 for (String ignoredEntry : ignoreList.split(","))
122 if (seqName.contains(ignoredEntry))
130 static String getDBRefId(DBRefEntry dbRef)
132 String ref = dbRef.getAccessionId().replaceAll("GO:", "");
137 * FTSRestClient specific query builder to recover associated structure data
138 * records for a sequence
141 * - seq to generate a query for
142 * @param wantedFields
143 * - fields to retrieve
144 * @param selectedFilterOpt
145 * - criterion for ranking results (e.g. resolution)
147 * - sort ascending or descending
151 public FTSRestResponse fetchStructuresMetaData(SequenceI seq,
152 Collection<FTSDataColumnI> wantedFields,
153 FilterOption selectedFilterOpt, boolean b) throws Exception
155 FTSRestResponse resultList;
156 FTSRestRequest tdbRequest = getTDBeaconsRequest(seq, wantedFields);
157 resultList = tdbRestClient.executeRequest(tdbRequest);
159 lastTdbRequest = tdbRequest;
163 private FTSRestRequest getTDBeaconsRequest(SequenceI seq,
164 Collection<FTSDataColumnI> wantedFields)
166 FTSRestRequest pdbRequest = new FTSRestRequest();
167 pdbRequest.setAllowEmptySeq(false);
168 pdbRequest.setResponseSize(500);
169 pdbRequest.setWantedFields(wantedFields);
170 String query = buildQuery(seq);
175 pdbRequest.setSearchTerm(query + ".json");
176 pdbRequest.setAssociatedSequence(seq);
181 public List<FilterOption> getAvailableFilterOptions(String VIEWS_FILTER)
183 List<FilterOption> filters = new ArrayList<FilterOption>();
185 new FilterOption(MessageManager.getString("label.best_quality"),
186 "overall_quality", VIEWS_FILTER, false));
187 filters.add(new FilterOption(
188 MessageManager.getString("label.best_resolution"), "resolution",
189 VIEWS_FILTER, false));
190 filters.add(new FilterOption(
191 MessageManager.getString("label.most_protein_chain"),
192 "number_of_protein_chains", VIEWS_FILTER, false));
193 filters.add(new FilterOption(
194 MessageManager.getString("label.most_bound_molecules"),
195 "number_of_bound_molecules", VIEWS_FILTER, false));
196 filters.add(new FilterOption(
197 MessageManager.getString("label.most_polymer_residues"),
198 "number_of_polymer_residues", VIEWS_FILTER, true));
204 * FTSRestClient specific query builder to pick top ranked entry from a
205 * fetchStructuresMetaData query
208 * - seq to generate a query for
209 * @param wantedFields
210 * - fields to retrieve
211 * @param selectedFilterOpt
212 * - criterion for ranking results (e.g. resolution)
214 * - sort ascending or descending
218 public FTSRestResponse selectFirstRankedQuery(SequenceI seq,
219 Collection<FTSData> collectedResults,
220 Collection<FTSDataColumnI> wantedFields, String fieldToFilterBy,
221 boolean b) throws Exception
224 TDBResultAnalyser analyser= new TDBResultAnalyser(seq,collectedResults, lastTdbRequest);
227 FTSRestResponse resultList = new FTSRestResponse();
229 List<FTSData> filteredResponse = analyser.getFilteredResponse();
231 List<FTSData> selectedStructures = analyser.selectStructures(filteredResponse);
232 resultList.setNumberOfItemsFound(selectedStructures.size());
233 resultList.setSearchSummary(selectedStructures);
238 public PDBEntry[] collectSelectedRows(JTable restable, int[] selectedRows,
239 List<SequenceI> selectedSeqsToView)
241 int refSeqColIndex = restable.getColumn("Ref Sequence").getModelIndex();
243 PDBEntry[] pdbEntriesToView = new PDBEntry[selectedRows.length];
245 int idColumnIndex = restable.getColumn("Model id").getModelIndex();
246 int urlColumnIndex = restable.getColumn("Url").getModelIndex();
247 int typeColumnIndex = restable.getColumn("Provider").getModelIndex();
248 int categoryColumnIndex = restable.getColumn("Model Category")
250 final int up_start_idx = restable.getColumn("Uniprot Start").getModelIndex();
251 final int up_end_idx = restable.getColumn("Uniprot End").getModelIndex();
255 Integer[] sellist = new Integer[selectedRows.length];
256 for (Integer row: selectedRows)
260 // Sort rows by coverage
261 Arrays.sort(sellist,new Comparator<Integer>()
264 public int compare(Integer o1, Integer o2)
266 int o1_xt = ((Integer)restable.getValueAt(o1, up_end_idx)) - (Integer)restable.getValueAt(o1, up_start_idx);
267 int o2_xt = ((Integer)restable.getValueAt(o2, up_end_idx)) - (Integer)restable.getValueAt(o2, up_start_idx);
273 for (int row : sellist)
275 // unique id - could be a horrible hash
277 String pdbIdStr = restable.getValueAt(row, idColumnIndex).toString();
278 String urlStr = restable.getValueAt(row, urlColumnIndex).toString();
279 String typeColumn = restable.getValueAt(row, typeColumnIndex)
281 SequenceI selectedSeq = (SequenceI) restable.getValueAt(row,
283 selectedSeqsToView.add(selectedSeq);
284 PDBEntry pdbEntry = selectedSeq.getPDBEntry(pdbIdStr);
285 if (pdbEntry == null)
287 pdbEntry = getFindEntry(pdbIdStr, selectedSeq.getAllPDBEntries());
290 if (pdbEntry == null)
292 pdbEntry = new PDBEntry();
293 pdbEntry.setId(pdbIdStr);
294 pdbEntry.setType(PDBEntry.Type.MMCIF);
295 if (!"PDBe".equalsIgnoreCase(typeColumn))
297 pdbEntry.setRetrievalUrl(urlStr);
299 selectedSeq.getDatasetSequence().addPDBId(pdbEntry);
301 pdbEntriesToView[count++] = pdbEntry;
303 return pdbEntriesToView;
307 protected FTSRestRequest getLastFTSRequest()
309 return lastTdbRequest;
313 * generate a query for PDBFTS to retrieve structure metadata
315 * @param ftsRestRequest
320 public String buildPDBFTSQueryFor(FTSRestResponse upResponse)
322 List<String> pdbIds = new ArrayList<String>();
323 int idx_modelId = getLastFTSRequest().getFieldIndex("Model id");
324 int idx_provider = getLastFTSRequest().getFieldIndex("Provider");
325 for (FTSData row : upResponse.getSearchSummary())
327 String id = (String) row.getSummaryData()[idx_modelId];
328 String provider = (String) row.getSummaryData()[idx_provider];
329 if ("PDBe".equalsIgnoreCase(provider))
334 return String.join(" OR ", pdbIds).toString();
338 * query PDBe for structure metadata
342 * @return FTSRestResponse via PDBStructureChooserQuerySource
344 public FTSRestResponse fetchStructuresMetaDataFor(
345 PDBStructureChooserQuerySource pdbquery,
346 FTSRestResponse upResponse) throws Exception
349 String pdb_Query = buildPDBFTSQueryFor(upResponse);
351 FTSRestResponse resultList;
352 FTSRestRequest pdbRequest = new FTSRestRequest();
353 pdbRequest.setAllowEmptySeq(false);
354 pdbRequest.setResponseSize(500);
355 pdbRequest.setFieldToSearchBy("(");
356 // pdbRequest.setFieldToSortBy("pdb_id");
357 pdbRequest.setWantedFields(
358 pdbquery.getDocFieldPrefs().getStructureSummaryFields());
359 pdbRequest.setSearchTerm(pdb_Query + ")");
360 resultList = pdbquery.executePDBFTSRestRequest(pdbRequest);
362 lastPdbRequest = pdbRequest;
366 public FTSRestResponse joinResponses(FTSRestResponse upResponse,
367 FTSRestResponse pdbResponse)
369 int idx_provider = getLastFTSRequest().getFieldIndex("Provider");
371 int idx_modelId = getLastFTSRequest().getFieldIndex("Model id");
372 int pdbIdx = lastPdbRequest.getFieldIndex("pdb_id");
373 for (FTSData row : upResponse.getSearchSummary())
375 String id = (String) row.getSummaryData()[idx_modelId];
376 String provider = (String) row.getSummaryData()[idx_provider];
377 if ("PDBe".equalsIgnoreCase(provider))
379 for (FTSData pdbrow : pdbResponse.getSearchSummary())
381 String pdbid = (String) pdbrow.getSummaryData()[pdbIdx];
382 if (id.equalsIgnoreCase(pdbid))
384 // often multiple entries per PDB ID so we bail after first
386 // append to FTSRestResponse array
391 // TODO Auto-generated method stub