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;
161 // Query the PDB and add additional metadata
162 FTSRestResponse pdbResponse = fetchStructuresMetaDataFor(getPDBQuerySource(), resultList);
163 FTSRestResponse joinedResp = joinResponses(resultList,
168 PDBStructureChooserQuerySource pdbQuerySource=null;
169 private PDBStructureChooserQuerySource getPDBQuerySource()
171 if (pdbQuerySource==null)
173 pdbQuerySource = new PDBStructureChooserQuerySource();
175 return pdbQuerySource;
178 private FTSRestRequest getTDBeaconsRequest(SequenceI seq,
179 Collection<FTSDataColumnI> wantedFields)
181 FTSRestRequest pdbRequest = new FTSRestRequest();
182 pdbRequest.setAllowEmptySeq(false);
183 pdbRequest.setResponseSize(500);
184 pdbRequest.setWantedFields(wantedFields);
185 String query = buildQuery(seq);
190 pdbRequest.setSearchTerm(query + ".json");
191 pdbRequest.setAssociatedSequence(seq);
196 public List<FilterOption> getAvailableFilterOptions(String VIEWS_FILTER)
198 List<FilterOption> filters = new ArrayList<FilterOption>();
200 new FilterOption(MessageManager.getString("label.best_quality"),
201 "overall_quality", VIEWS_FILTER, false));
202 filters.add(new FilterOption(
203 MessageManager.getString("label.best_resolution"), "resolution",
204 VIEWS_FILTER, false));
205 filters.add(new FilterOption(
206 MessageManager.getString("label.most_protein_chain"),
207 "number_of_protein_chains", VIEWS_FILTER, false));
208 filters.add(new FilterOption(
209 MessageManager.getString("label.most_bound_molecules"),
210 "number_of_bound_molecules", VIEWS_FILTER, false));
211 filters.add(new FilterOption(
212 MessageManager.getString("label.most_polymer_residues"),
213 "number_of_polymer_residues", VIEWS_FILTER, true));
219 * FTSRestClient specific query builder to pick top ranked entry from a
220 * fetchStructuresMetaData query
223 * - seq to generate a query for
224 * @param wantedFields
225 * - fields to retrieve
226 * @param selectedFilterOpt
227 * - criterion for ranking results (e.g. resolution)
229 * - sort ascending or descending
233 public FTSRestResponse selectFirstRankedQuery(SequenceI seq,
234 Collection<FTSData> collectedResults,
235 Collection<FTSDataColumnI> wantedFields, String fieldToFilterBy,
236 boolean b) throws Exception
239 TDBResultAnalyser analyser= new TDBResultAnalyser(seq,collectedResults, lastTdbRequest);
242 FTSRestResponse resultList = new FTSRestResponse();
244 List<FTSData> filteredResponse = analyser.getFilteredResponse();
246 List<FTSData> selectedStructures = analyser.selectStructures(filteredResponse);
247 resultList.setNumberOfItemsFound(selectedStructures.size());
248 resultList.setSearchSummary(selectedStructures);
253 public PDBEntry[] collectSelectedRows(JTable restable, int[] selectedRows,
254 List<SequenceI> selectedSeqsToView)
256 int refSeqColIndex = restable.getColumn("Ref Sequence").getModelIndex();
258 PDBEntry[] pdbEntriesToView = new PDBEntry[selectedRows.length];
260 int idColumnIndex = restable.getColumn("Model id").getModelIndex();
261 int urlColumnIndex = restable.getColumn("Url").getModelIndex();
262 int typeColumnIndex = restable.getColumn("Provider").getModelIndex();
263 int categoryColumnIndex = restable.getColumn("Model Category")
265 final int up_start_idx = restable.getColumn("Uniprot Start").getModelIndex();
266 final int up_end_idx = restable.getColumn("Uniprot End").getModelIndex();
270 Integer[] sellist = new Integer[selectedRows.length];
271 for (Integer row: selectedRows)
275 // Sort rows by coverage
276 Arrays.sort(sellist,new Comparator<Integer>()
279 public int compare(Integer o1, Integer o2)
281 int o1_xt = ((Integer)restable.getValueAt(o1, up_end_idx)) - (Integer)restable.getValueAt(o1, up_start_idx);
282 int o2_xt = ((Integer)restable.getValueAt(o2, up_end_idx)) - (Integer)restable.getValueAt(o2, up_start_idx);
288 for (int row : sellist)
290 // unique id - could be a horrible hash
292 String pdbIdStr = restable.getValueAt(row, idColumnIndex).toString();
293 String urlStr = restable.getValueAt(row, urlColumnIndex).toString();
294 String typeColumn = restable.getValueAt(row, typeColumnIndex)
296 SequenceI selectedSeq = (SequenceI) restable.getValueAt(row,
298 selectedSeqsToView.add(selectedSeq);
299 PDBEntry pdbEntry = selectedSeq.getPDBEntry(pdbIdStr);
300 if (pdbEntry == null)
302 pdbEntry = getFindEntry(pdbIdStr, selectedSeq.getAllPDBEntries());
305 if (pdbEntry == null)
307 pdbEntry = new PDBEntry();
308 pdbEntry.setId(pdbIdStr);
309 pdbEntry.setType(PDBEntry.Type.MMCIF);
310 if (!"PDBe".equalsIgnoreCase(typeColumn))
312 pdbEntry.setRetrievalUrl(urlStr);
314 selectedSeq.getDatasetSequence().addPDBId(pdbEntry);
316 pdbEntriesToView[count++] = pdbEntry;
318 return pdbEntriesToView;
322 protected FTSRestRequest getLastFTSRequest()
324 return lastTdbRequest;
328 * generate a query for PDBFTS to retrieve structure metadata
330 * @param ftsRestRequest
335 public String buildPDBFTSQueryFor(FTSRestResponse upResponse)
337 List<String> pdbIds = new ArrayList<String>();
338 int idx_modelId = getLastFTSRequest().getFieldIndex("Model id");
339 int idx_provider = getLastFTSRequest().getFieldIndex("Provider");
340 for (FTSData row : upResponse.getSearchSummary())
342 String id = (String) row.getSummaryData()[idx_modelId];
343 String provider = (String) row.getSummaryData()[idx_provider];
344 if ("PDBe".equalsIgnoreCase(provider))
349 return String.join(" OR ", pdbIds).toString();
353 * query PDBe for structure metadata
357 * @return FTSRestResponse via PDBStructureChooserQuerySource
359 public FTSRestResponse fetchStructuresMetaDataFor(
360 PDBStructureChooserQuerySource pdbquery,
361 FTSRestResponse upResponse) throws Exception
364 String pdb_Query = buildPDBFTSQueryFor(upResponse);
366 FTSRestResponse resultList;
367 FTSRestRequest pdbRequest = new FTSRestRequest();
368 pdbRequest.setAllowEmptySeq(false);
369 pdbRequest.setResponseSize(500);
370 pdbRequest.setFieldToSearchBy("(");
371 // pdbRequest.setFieldToSortBy("pdb_id");
372 pdbRequest.setWantedFields(
373 pdbquery.getDocFieldPrefs().getStructureSummaryFields());
374 pdbRequest.setSearchTerm(pdb_Query + ")");
375 resultList = pdbquery.executePDBFTSRestRequest(pdbRequest);
377 lastPdbRequest = pdbRequest;
381 public FTSRestResponse joinResponses(FTSRestResponse upResponse,
382 FTSRestResponse pdbResponse)
384 int idx_provider = getLastFTSRequest().getFieldIndex("Provider");
386 int idx_modelId = getLastFTSRequest().getFieldIndex("Model id");
387 int pdbIdx = lastPdbRequest.getFieldIndex("PDB Id");
388 int pdbTitle_idx = lastPdbRequest.getFieldIndex("Title");
389 int tdbTitle_idx = getLastFTSRequest().getFieldIndex("Title");
391 List<FTSData> joinedRows = new ArrayList<FTSData>();
392 for (final FTSData row : upResponse.getSearchSummary())
394 String id = (String) row.getSummaryData()[idx_modelId];
395 String provider = (String) row.getSummaryData()[idx_provider];
396 if ("PDBe".equalsIgnoreCase(provider))
398 for (final FTSData pdbrow : pdbResponse.getSearchSummary())
400 String pdbid = (String) pdbrow.getSummaryData()[pdbIdx];
401 if (id.equalsIgnoreCase(pdbid))
403 row.getSummaryData()[tdbTitle_idx] = pdbrow
404 .getSummaryData()[pdbTitle_idx];
408 row.getSummaryData()[tdbTitle_idx] = "Model from TDB";