From 2e3c61cedbe9185548ecfecad806c9e4f67f43c2 Mon Sep 17 00:00:00 2001 From: Jim Procter Date: Mon, 6 Sep 2021 14:48:46 +0100 Subject: [PATCH] JAL-3829 work in progress - look up additional metadata from PDBe for structures discovered via TDBFTS --- .../PDBStructureChooserQuerySource.java | 6 + .../ThreeDBStructureChooserQuerySource.java | 155 +++++++++++++++----- .../StructureChooserQuerySourceTest.java | 43 ++++-- 3 files changed, 156 insertions(+), 48 deletions(-) diff --git a/src/jalview/gui/structurechooser/PDBStructureChooserQuerySource.java b/src/jalview/gui/structurechooser/PDBStructureChooserQuerySource.java index 3d1b982..75e7fc0 100644 --- a/src/jalview/gui/structurechooser/PDBStructureChooserQuerySource.java +++ b/src/jalview/gui/structurechooser/PDBStructureChooserQuerySource.java @@ -355,4 +355,10 @@ public class PDBStructureChooserQuerySource return lastPdbRequest; } + + public FTSRestResponse executePDBFTSRestRequest(FTSRestRequest pdbRequest) throws Exception + { + return pdbRestClient.executeRequest(pdbRequest); + } + } \ No newline at end of file diff --git a/src/jalview/gui/structurechooser/ThreeDBStructureChooserQuerySource.java b/src/jalview/gui/structurechooser/ThreeDBStructureChooserQuerySource.java index 0bf9fdb..b3242de 100644 --- a/src/jalview/gui/structurechooser/ThreeDBStructureChooserQuerySource.java +++ b/src/jalview/gui/structurechooser/ThreeDBStructureChooserQuerySource.java @@ -13,6 +13,7 @@ import jalview.datamodel.DBRefEntry; import jalview.datamodel.DBRefSource; import jalview.datamodel.PDBEntry; import jalview.datamodel.SequenceI; +import jalview.fts.api.FTSData; import jalview.fts.api.FTSDataColumnI; import jalview.fts.api.FTSRestClientI; import jalview.fts.core.FTSDataColumnPreferences; @@ -38,6 +39,8 @@ public class ThreeDBStructureChooserQuerySource protected FTSRestClientI tdbRestClient; + private FTSRestRequest lastPdbRequest; + public ThreeDBStructureChooserQuerySource() { tdbRestClient = TDBeaconsFTSRestClient.getInstance(); @@ -47,10 +50,10 @@ public class ThreeDBStructureChooserQuerySource } - /** - * Builds a query string for a given sequences using its DBRef entries - * 3d Beacons is only useful for uniprot IDs + * Builds a query string for a given sequences using its DBRef entries 3d + * Beacons is only useful for uniprot IDs + * * @param seq * the sequences to build a query for * @return the built query string @@ -77,12 +80,13 @@ public class ThreeDBStructureChooserQuerySource if (isValidSeqName(getDBRefId(dbRef)) && queryBuilder.length() < MAX_QLENGTH) { - if (dbRef.getSource().equalsIgnoreCase(DBRefSource.UNIPROT) && dbRef.isCanonical()) + if (dbRef.getSource().equalsIgnoreCase(DBRefSource.UNIPROT) + && dbRef.isCanonical()) { - // TODO: pick best Uniprot accession - isUniProtRefsFound=true; + // TODO: pick best Uniprot accession + isUniProtRefsFound = true; return getDBRefId(dbRef); - + } } } @@ -90,8 +94,6 @@ public class ThreeDBStructureChooserQuerySource return null; } - - /** * Ensures sequence ref names are not less than 3 characters and does not * contain a database name @@ -154,16 +156,17 @@ public class ThreeDBStructureChooserQuerySource lastTdbRequest = tdbRequest; return resultList; } - - private FTSRestRequest getTDBeaconsRequest(SequenceI seq, Collection wantedFields) + private FTSRestRequest getTDBeaconsRequest(SequenceI seq, + Collection wantedFields) { FTSRestRequest pdbRequest = new FTSRestRequest(); pdbRequest.setAllowEmptySeq(false); pdbRequest.setResponseSize(500); pdbRequest.setWantedFields(wantedFields); String query = buildQuery(seq); - if (query==null) { + if (query == null) + { return null; } pdbRequest.setSearchTerm(query + ".json"); @@ -171,16 +174,16 @@ public class ThreeDBStructureChooserQuerySource return pdbRequest; } -@Override + @Override public List getAvailableFilterOptions(String VIEWS_FILTER) { List filters = new ArrayList(); + filters.add( + new FilterOption(MessageManager.getString("label.best_quality"), + "overall_quality", VIEWS_FILTER, false)); filters.add(new FilterOption( - MessageManager.getString("label.best_quality"), - "overall_quality", VIEWS_FILTER, false)); - filters.add(new FilterOption( - MessageManager.getString("label.best_resolution"), - "resolution", VIEWS_FILTER, false)); + MessageManager.getString("label.best_resolution"), "resolution", + VIEWS_FILTER, false)); filters.add(new FilterOption( MessageManager.getString("label.most_protein_chain"), "number_of_protein_chains", VIEWS_FILTER, false)); @@ -190,9 +193,10 @@ public class ThreeDBStructureChooserQuerySource filters.add(new FilterOption( MessageManager.getString("label.most_polymer_residues"), "number_of_polymer_residues", VIEWS_FILTER, true)); - + return filters; } + /** * FTSRestClient specific query builder to pick top ranked entry from a * fetchStructuresMetaData query @@ -215,12 +219,13 @@ public class ThreeDBStructureChooserQuerySource FTSRestResponse resultList; FTSRestRequest pdbRequest = getTDBeaconsRequest(seq, wantedFields); - if (pdbRequest == null) { + if (pdbRequest == null) + { return null; } pdbRequest.setResponseSize(1); resultList = tdbRestClient.executeRequest(pdbRequest); - + // TODO: client side filtering - sort results and pick top one (or N) lastTdbRequest = pdbRequest; @@ -231,25 +236,23 @@ public class ThreeDBStructureChooserQuerySource public PDBEntry[] collectSelectedRows(JTable restable, int[] selectedRows, List selectedSeqsToView) { - int refSeqColIndex = restable.getColumn("Ref Sequence") - .getModelIndex(); + int refSeqColIndex = restable.getColumn("Ref Sequence").getModelIndex(); - PDBEntry[] pdbEntriesToView=new PDBEntry[selectedRows.length]; + PDBEntry[] pdbEntriesToView = new PDBEntry[selectedRows.length]; int count = 0; 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 categoryColumnIndex = restable.getColumn("Model Category") + .getModelIndex(); + for (int row : selectedRows) { // unique id - could be a horrible hash - - String pdbIdStr = restable.getValueAt(row,idColumnIndex) - .toString(); - String urlStr = restable.getValueAt(row,urlColumnIndex) - .toString(); - String typeColumn = restable.getValueAt(row,typeColumnIndex) + + String pdbIdStr = restable.getValueAt(row, idColumnIndex).toString(); + String urlStr = restable.getValueAt(row, urlColumnIndex).toString(); + String typeColumn = restable.getValueAt(row, typeColumnIndex) .toString(); SequenceI selectedSeq = (SequenceI) restable.getValueAt(row, refSeqColIndex); @@ -257,8 +260,7 @@ public class ThreeDBStructureChooserQuerySource PDBEntry pdbEntry = selectedSeq.getPDBEntry(pdbIdStr); if (pdbEntry == null) { - pdbEntry = getFindEntry(pdbIdStr, - selectedSeq.getAllPDBEntries()); + pdbEntry = getFindEntry(pdbIdStr, selectedSeq.getAllPDBEntries()); } if (pdbEntry == null) @@ -277,10 +279,93 @@ public class ThreeDBStructureChooserQuerySource return pdbEntriesToView; } - @Override protected FTSRestRequest getLastFTSRequest() { return lastTdbRequest; } + + /** + * generate a query for PDBFTS to retrieve structure metadata + * + * @param ftsRestRequest + * @param upResponse + * @return + */ + + public String buildPDBFTSQueryFor(FTSRestResponse upResponse) + { + List pdbIds = new ArrayList(); + int idx_modelId = getLastFTSRequest().getFieldIndex("Model id"); + int idx_provider = getLastFTSRequest().getFieldIndex("Provider"); + for (FTSData row : upResponse.getSearchSummary()) + { + String id = (String) row.getSummaryData()[idx_modelId]; + String provider = (String) row.getSummaryData()[idx_provider]; + if ("PDBe".equalsIgnoreCase(provider)) + { + pdbIds.add(id); + } + } + return String.join(" OR ", pdbIds).toString(); + } + + /** + * query PDBe for structure metadata + * + * @param pdbquery + * @param upResponse + * @return FTSRestResponse via PDBStructureChooserQuerySource + */ + public FTSRestResponse fetchStructuresMetaDataFor( + PDBStructureChooserQuerySource pdbquery, + FTSRestResponse upResponse) throws Exception + { + + String pdb_Query = buildPDBFTSQueryFor(upResponse); + + 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; + } + + public FTSRestResponse joinResponses(FTSRestResponse upResponse, + FTSRestResponse pdbResponse) + { + int idx_provider = getLastFTSRequest().getFieldIndex("Provider"); + // join on + int idx_modelId = getLastFTSRequest().getFieldIndex("Model id"); + int pdbIdx = lastPdbRequest.getFieldIndex("pdb_id"); + for (FTSData row : upResponse.getSearchSummary()) + { + String id = (String) row.getSummaryData()[idx_modelId]; + String provider = (String) row.getSummaryData()[idx_provider]; + if ("PDBe".equalsIgnoreCase(provider)) + { + for (FTSData pdbrow : pdbResponse.getSearchSummary()) + { + String pdbid = (String) pdbrow.getSummaryData()[pdbIdx]; + if (id.equalsIgnoreCase(pdbid)) + { + // often multiple entries per PDB ID so we bail after first + // get wanted fields + // append to FTSRestResponse array + } + } + } + } + // TODO Auto-generated method stub + return null; + } + } \ No newline at end of file diff --git a/test/jalview/gui/structurechooser/StructureChooserQuerySourceTest.java b/test/jalview/gui/structurechooser/StructureChooserQuerySourceTest.java index b6b4615..f492ce6 100644 --- a/test/jalview/gui/structurechooser/StructureChooserQuerySourceTest.java +++ b/test/jalview/gui/structurechooser/StructureChooserQuerySourceTest.java @@ -21,8 +21,12 @@ package jalview.gui.structurechooser; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; + import java.util.Vector; +import org.junit.Assert; import org.testng.AssertJUnit; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeClass; @@ -35,8 +39,11 @@ import jalview.datamodel.PDBEntry; import jalview.datamodel.Sequence; import jalview.datamodel.SequenceI; import jalview.fts.core.FTSRestRequest; +import jalview.fts.core.FTSRestResponse; +import jalview.fts.service.pdb.PDBFTSRestClient; import jalview.fts.threedbeacons.TDBeaconsFTSRestClientTest; import jalview.gui.JvOptionPane; +import jalview.jbgui.FilterOption; public class StructureChooserQuerySourceTest { @@ -242,21 +249,31 @@ public class StructureChooserQuerySourceTest public void cascadingThreeDBandPDBQuerys() { TDBeaconsFTSRestClientTest.setMock(); - - StructureChooserQuerySource scquery = StructureChooserQuerySource.getQuerySourceFor(new SequenceI[] { upSeq}); + PDBFTSRestClient.setMock(); + ThreeDBStructureChooserQuerySource tdbquery = new ThreeDBStructureChooserQuerySource(); + PDBStructureChooserQuerySource pdbquery = new PDBStructureChooserQuerySource(); + - // query TDB for doc - // query PDBe for PDB entry metadata - // Combine - FTSRestRequest tdbQuery = new FTSRestRequest(); - tdbQuery.setResponseSize(100); - tdbQuery.setFieldToSearchBy(""); - tdbQuery.setSearchTerm(scquery.buildQuery(upSeq)); - tdbQuery.setWantedFields(scquery.getDocFieldPrefs().getStructureSummaryFields()); - //scquery.fetchStructuresMetaData(upSeq, null, null, false); - String secondaryPdbQuery; - //secondaryPdbQuery = ((ThreeDBStructureChooserQuerySource)scquery).buildPDBFTSquery(); + FTSRestResponse upResponse = null; + FTSRestResponse pdbResponse = null; + + try { + upResponse = tdbquery.fetchStructuresMetaData(upSeq, tdbquery.getDocFieldPrefs().getStructureSummaryFields(), null, false); + // NB Could have race condition here + String pdb_Query = tdbquery.buildPDBFTSQueryFor(upResponse); + assertTrue(pdb_Query.trim().length()>0); + pdbResponse = tdbquery.fetchStructuresMetaDataFor(pdbquery, upResponse); + assertTrue(pdbResponse.getNumberOfItemsFound()>0); + FTSRestResponse joinedResp = tdbquery.joinResponses(upResponse, pdbResponse); + assertEquals(upResponse.getNumberOfItemsFound(),joinedResp.getNumberOfItemsFound()); + + } catch (Exception x) + { + x.printStackTrace(); + Assert.fail("Unexpected Exception"); + } + StructureChooserQuerySource scquery = StructureChooserQuerySource.getQuerySourceFor(new SequenceI[] { upSeq}); } -- 1.7.10.2