X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fgui%2Fstructurechooser%2FThreeDBStructureChooserQuerySource.java;h=175ad77f05dd6e3dfe2f25a144efaad3cedc0a4b;hb=e2c95a076f6ac8fae4922781e8008bae5513d6aa;hp=ff414ddb8d79658a09ca1da82072aca3d916bbc3;hpb=2ed25b9d62b190d26c2ec68c60d3cf96c5cc1c7c;p=jalview.git diff --git a/src/jalview/gui/structurechooser/ThreeDBStructureChooserQuerySource.java b/src/jalview/gui/structurechooser/ThreeDBStructureChooserQuerySource.java index ff414dd..175ad77 100644 --- a/src/jalview/gui/structurechooser/ThreeDBStructureChooserQuerySource.java +++ b/src/jalview/gui/structurechooser/ThreeDBStructureChooserQuerySource.java @@ -1,9 +1,28 @@ +/* + * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$) + * Copyright (C) $$Year-Rel$$ The Jalview Authors + * + * This file is part of Jalview. + * + * Jalview is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 + * of the License, or (at your option) any later version. + * + * Jalview is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Jalview. If not, see . + * The Jalview Authors are detailed in the 'AUTHORS' file. + */ package jalview.gui.structurechooser; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; -import java.util.Collections; import java.util.Comparator; import java.util.HashSet; import java.util.LinkedHashSet; @@ -13,6 +32,7 @@ import java.util.Set; import javax.swing.JTable; +import jalview.bin.Console; import jalview.datamodel.DBRefEntry; import jalview.datamodel.DBRefSource; import jalview.datamodel.PDBEntry; @@ -24,9 +44,9 @@ import jalview.fts.core.FTSDataColumnPreferences; import jalview.fts.core.FTSDataColumnPreferences.PreferenceSource; import jalview.fts.core.FTSRestRequest; import jalview.fts.core.FTSRestResponse; +import jalview.fts.service.threedbeacons.TDB_FTSData; import jalview.fts.service.threedbeacons.TDBeaconsFTSRestClient; import jalview.jbgui.FilterOption; -import jalview.util.MessageManager; /** * logic for querying the 3DBeacons API for structures of sequences @@ -45,8 +65,6 @@ public class ThreeDBStructureChooserQuerySource private static final String FILTER_SOURCE_PREFIX = "only_"; - private static int MAX_QLENGTH = 7820; - protected FTSRestRequest lastTdbRequest; protected FTSRestClientI tdbRestClient; @@ -76,37 +94,41 @@ public class ThreeDBStructureChooserQuerySource public String buildQuery(SequenceI seq) { - boolean isPDBRefsFound = false; - boolean isUniProtRefsFound = false; - StringBuilder queryBuilder = new StringBuilder(); - Set seqRefs = new LinkedHashSet<>(); - - /* - * note PDBs as DBRefEntry so they are not duplicated in query - */ - Set pdbids = new HashSet<>(); - List refs = seq.getDBRefs(); + int ib = checkUniprotRefs(refs); + if (ib > -1) + { + return getDBRefId(refs.get(ib)); + } + return null; + } + + /** + * Searches DBRefEntry for uniprot refs + * + * @param seq + * @return -2 if no uniprot refs, -1 if no canonical ref., otherwise index of + * Uniprot canonical DBRefEntry + */ + public static int checkUniprotRefs(List refs) + { + boolean hasUniprot = false; if (refs != null && refs.size() != 0) { for (int ib = 0, nb = refs.size(); ib < nb; ib++) { DBRefEntry dbRef = refs.get(ib); - if (isValidSeqName(getDBRefId(dbRef)) - && queryBuilder.length() < MAX_QLENGTH) + if (dbRef.getSource().equalsIgnoreCase(DBRefSource.UNIPROT)) { - if (dbRef.getSource().equalsIgnoreCase(DBRefSource.UNIPROT) - && dbRef.isCanonical()) + hasUniprot = true; + if (dbRef.isCanonical()) { - // TODO: pick best Uniprot accession - isUniProtRefsFound = true; - return getDBRefId(dbRef); - + return ib; } } } } - return null; + return hasUniprot ? -1 : -2; } /** @@ -118,7 +140,6 @@ public class ThreeDBStructureChooserQuerySource */ static boolean isValidSeqName(String seqName) { - // System.out.println("seqName : " + seqName); String ignoreList = "pdb,uniprot,swiss-prot"; if (seqName.length() < 3) { @@ -128,7 +149,7 @@ public class ThreeDBStructureChooserQuerySource { return false; } - seqName = seqName.toLowerCase(); + seqName = seqName.toLowerCase(Locale.ROOT); for (String ignoredEntry : ignoreList.split(",")) { if (seqName.contains(ignoredEntry)) @@ -165,17 +186,20 @@ public class ThreeDBStructureChooserQuerySource FilterOption selectedFilterOpt, boolean b) throws Exception { FTSRestResponse resultList; - if (selectedFilterOpt!=null && tdBeaconsFilter(selectedFilterOpt.getValue())) + if (selectedFilterOpt != null + && tdBeaconsFilter(selectedFilterOpt.getValue())) { FTSRestRequest tdbRequest = getTDBeaconsRequest(seq, wantedFields); resultList = tdbRestClient.executeRequest(tdbRequest); lastTdbRequest = tdbRequest; + if (resultList != null) + { // Query the PDB and add additional metadata + List pdbResponse = fetchStructuresMetaDataFor( + getPDBQuerySource(), resultList); - // Query the PDB and add additional metadata - FTSRestResponse pdbResponse = fetchStructuresMetaDataFor( - getPDBQuerySource(), resultList); - FTSRestResponse joinedResp = joinResponses(resultList, pdbResponse); + resultList = joinResponses(resultList, pdbResponse); + } return resultList; } // use the PDBFTS directly @@ -183,7 +207,7 @@ public class ThreeDBStructureChooserQuerySource wantedFields, selectedFilterOpt, b); lastTdbRequest = getPDBQuerySource().lastPdbRequest; lastPdbRequest = lastTdbRequest; // both queries the same - indicates we - // rank using PDBe + // rank using PDBe return resultList; } @@ -235,22 +259,43 @@ public class ThreeDBStructureChooserQuerySource public void updateAvailableFilterOptions(String VIEWS_FILTER, List xtantOptions, Collection tdbEntries) { - if (tdbEntries !=null && lastTdbRequest != null) + if (tdbEntries != null && lastTdbRequest != null) { - int prov_idx = lastTdbRequest.getFieldIndex("Provider"); - - for (FTSData row : tdbEntries) + boolean hasPDBe = false; + for (FTSData _row : tdbEntries) { - String provider = (String) row.getSummaryData()[prov_idx]; - FilterOption providerOpt = new FilterOption("3DB Provider - " + provider, - FILTER_SOURCE_PREFIX + provider, VIEWS_FILTER, - false, this); + // tdb returns custom object + TDB_FTSData row = (TDB_FTSData) _row; + String provider = row.getProvider(); + FilterOption providerOpt = new FilterOption( + "3DB Provider - " + provider, + FILTER_SOURCE_PREFIX + provider, VIEWS_FILTER, false, this); if (!xtantOptions.contains(providerOpt)) { - xtantOptions.add(1, - providerOpt); - tdBeaconsFilters.add(FILTER_SOURCE_PREFIX+provider); - + xtantOptions.add(1, providerOpt); + tdBeaconsFilters.add(FILTER_SOURCE_PREFIX + provider); + if ("PDBe".equalsIgnoreCase(provider)) + { + hasPDBe = true; + } + } + } + if (!hasPDBe) + { + // remove the PDBe options from the available filters + int op = 0; + while (op < xtantOptions.size()) + { + FilterOption filter = xtantOptions.get(op); + if (filter + .getQuerySource() instanceof PDBStructureChooserQuerySource) + { + xtantOptions.remove(op); + } + else + { + op++; + } } } } @@ -280,8 +325,9 @@ public class ThreeDBStructureChooserQuerySource @Override public boolean needsRefetch(FilterOption selectedFilterOpt) { - return selectedFilterOpt==null || !tdBeaconsFilter(selectedFilterOpt.getValue()) - && lastPdbRequest != lastTdbRequest; + return selectedFilterOpt == null + || !tdBeaconsFilter(selectedFilterOpt.getValue()) + && lastPdbRequest != lastTdbRequest; } /** @@ -304,7 +350,7 @@ public class ThreeDBStructureChooserQuerySource Collection wantedFields, String fieldToFilterBy, boolean b) throws Exception { - if (fieldToFilterBy!=null && tdBeaconsFilter(fieldToFilterBy)) + if (fieldToFilterBy != null && tdBeaconsFilter(fieldToFilterBy)) { TDBResultAnalyser analyser = new TDBResultAnalyser(seq, collectedResults, lastTdbRequest, fieldToFilterBy, @@ -336,8 +382,8 @@ public class ThreeDBStructureChooserQuerySource int idColumnIndex = restable.getColumn("Model id").getModelIndex(); int urlColumnIndex = restable.getColumn("Url").getModelIndex(); int typeColumnIndex = restable.getColumn("Provider").getModelIndex(); - int categoryColumnIndex = restable.getColumn("Model Category") - .getModelIndex(); + int humanUrl = restable.getColumn("Page URL").getModelIndex(); + int modelformat = restable.getColumn("Model Format").getModelIndex(); final int up_start_idx = restable.getColumn("Uniprot Start") .getModelIndex(); final int up_end_idx = restable.getColumn("Uniprot End") @@ -372,6 +418,10 @@ public class ThreeDBStructureChooserQuerySource String urlStr = restable.getValueAt(row, urlColumnIndex).toString(); String typeColumn = restable.getValueAt(row, typeColumnIndex) .toString(); + String modelPage = humanUrl < 1 ? null + : (String) restable.getValueAt(row, humanUrl); + String strucFormat = restable.getValueAt(row, modelformat).toString(); + SequenceI selectedSeq = (SequenceI) restable.getValueAt(row, refSeqColIndex); selectedSeqsToView.add(selectedSeq); @@ -385,13 +435,22 @@ public class ThreeDBStructureChooserQuerySource { pdbEntry = new PDBEntry(); pdbEntry.setId(pdbIdStr); - boolean hasCif = urlStr.toLowerCase(Locale.ENGLISH).endsWith("cif"); - boolean probablyPdb = urlStr.toLowerCase(Locale.ENGLISH).contains("pdb"); - pdbEntry.setType(hasCif ? PDBEntry.Type.MMCIF : probablyPdb ? PDBEntry.Type.PDB : PDBEntry.Type.FILE); + pdbEntry.setAuthoritative(true); + try + { + pdbEntry.setType(PDBEntry.Type.valueOf(strucFormat)); + } catch (Exception q) + { + Console.warn("Unknown filetype for 3D Beacons Model from: " + + strucFormat + " - " + pdbIdStr + " - " + modelPage); + } + if (!"PDBe".equalsIgnoreCase(typeColumn)) { pdbEntry.setRetrievalUrl(urlStr); } + pdbEntry.setProvider(typeColumn); + pdbEntry.setProviderPage(modelPage); selectedSeq.getDatasetSequence().addPDBId(pdbEntry); } pdbEntriesToView[count++] = pdbEntry; @@ -413,9 +472,10 @@ public class ThreeDBStructureChooserQuerySource * @return */ - public String buildPDBFTSQueryFor(FTSRestResponse upResponse) + public List buildPDBFTSQueryFor(FTSRestResponse upResponse) { - List pdbIds = new ArrayList(); + List ftsQueries = new ArrayList(); + Set pdbIds = new HashSet(); int idx_modelId = getLastFTSRequest().getFieldIndex("Model id"); int idx_provider = getLastFTSRequest().getFieldIndex("Provider"); for (FTSData row : upResponse.getSearchSummary()) @@ -427,7 +487,25 @@ public class ThreeDBStructureChooserQuerySource pdbIds.add(id); } } - return String.join(" OR ", pdbIds).toString(); + StringBuilder sb = new StringBuilder(); + for (String pdbId : pdbIds) + { + if (sb.length() > 2500) + { + ftsQueries.add(sb.toString()); + sb.setLength(0); + } + if (sb.length() > 0) + { + sb.append(" OR "); + } + sb.append(pdbId); + } + if (sb.length() > 0) + { + ftsQueries.add(sb.toString()); + } + return ftsQueries; } /** @@ -437,58 +515,86 @@ public class ThreeDBStructureChooserQuerySource * @param upResponse * @return FTSRestResponse via PDBStructureChooserQuerySource */ - public FTSRestResponse fetchStructuresMetaDataFor( + public List fetchStructuresMetaDataFor( PDBStructureChooserQuerySource pdbquery, FTSRestResponse upResponse) throws Exception { - - String pdb_Query = buildPDBFTSQueryFor(upResponse); - if (pdb_Query.length()==0) + List pdb_Queries = buildPDBFTSQueryFor(upResponse); + if (pdb_Queries.size() == 0) { return null; } - FTSRestResponse resultList; - FTSRestRequest pdbRequest = new FTSRestRequest(); - pdbRequest.setAllowEmptySeq(false); - pdbRequest.setResponseSize(500); - pdbRequest.setFieldToSearchBy("("); - // pdbRequest.setFieldToSortBy("pdb_id"); - pdbRequest.setWantedFields( - pdbquery.getDocFieldPrefs().getStructureSummaryFields()); - pdbRequest.setSearchTerm(pdb_Query + ")"); - - resultList = pdbquery.executePDBFTSRestRequest(pdbRequest); - - lastPdbRequest = pdbRequest; - return resultList; + List results = new ArrayList(); + + for (String pdb_Query : pdb_Queries) + { + FTSRestResponse resultList; + FTSRestRequest pdbRequest = new FTSRestRequest(); + pdbRequest.setAllowEmptySeq(false); + pdbRequest.setResponseSize(500); + pdbRequest.setFieldToSearchBy("("); + // pdbRequest.setFieldToSortBy("pdb_id"); + pdbRequest.setWantedFields( + pdbquery.getDocFieldPrefs().getStructureSummaryFields()); + pdbRequest.setSearchTerm(pdb_Query + ")"); + + // handle exceptions like server errors here - means the threedbeacons + // discovery isn't broken by issues to do with the PDBe SOLR api + try + { + resultList = pdbquery.executePDBFTSRestRequest(pdbRequest); + results.add(resultList); + lastPdbRequest = pdbRequest; + } catch (Exception ex) + { + Console.error("PDBFTSQuery failed", ex); + } + + } + + return results; } public FTSRestResponse joinResponses(FTSRestResponse upResponse, - FTSRestResponse pdbResponse) + List pdbResponses) { + boolean hasPdbResp = lastPdbRequest != null; + int idx_provider = getLastFTSRequest().getFieldIndex("Provider"); // join on int idx_modelId = getLastFTSRequest().getFieldIndex("Model id"); - int pdbIdx = lastPdbRequest.getFieldIndex("PDB Id"); - int pdbTitle_idx = lastPdbRequest.getFieldIndex("Title"); + int pdbIdx = hasPdbResp ? lastPdbRequest.getFieldIndex("PDB Id") : -1; + int pdbTitle_idx = hasPdbResp ? lastPdbRequest.getFieldIndex("Title") + : -1; int tdbTitle_idx = getLastFTSRequest().getFieldIndex("Title"); - List joinedRows = new ArrayList(); for (final FTSData row : upResponse.getSearchSummary()) { String id = (String) row.getSummaryData()[idx_modelId]; String provider = (String) row.getSummaryData()[idx_provider]; if ("PDBe".equalsIgnoreCase(provider)) { - for (final FTSData pdbrow : pdbResponse.getSearchSummary()) + if (!hasPdbResp) { - String pdbid = (String) pdbrow.getSummaryData()[pdbIdx]; - if (id.equalsIgnoreCase(pdbid)) + System.out.println( + "Warning: seems like we couldn't get to the PDBe search interface."); + } + else + { + for (final FTSRestResponse pdbResponse : pdbResponses) { - row.getSummaryData()[tdbTitle_idx] = pdbrow - .getSummaryData()[pdbTitle_idx]; + for (final FTSData pdbrow : pdbResponse.getSearchSummary()) + { + String pdbid = (String) pdbrow.getSummaryData()[pdbIdx]; + if (id.equalsIgnoreCase(pdbid)) + { + row.getSummaryData()[tdbTitle_idx] = pdbrow + .getSummaryData()[pdbTitle_idx]; + } + } } } + } else { @@ -498,4 +604,22 @@ public class ThreeDBStructureChooserQuerySource return upResponse; } + public TDB_FTSData getFTSDataFor(JTable restable, int selectedRow, + Collection discoveredStructuresSet) + { + int idColumnIndex = restable.getColumn("Model id").getModelIndex(); + + String modelId = (String) restable.getValueAt(selectedRow, + idColumnIndex); + for (FTSData row : discoveredStructuresSet) + { + if (row instanceof TDB_FTSData + && ((TDB_FTSData) row).getModelId().equals(modelId)) + { + return ((TDB_FTSData) row); + } + } + return null; + } + } \ No newline at end of file