From 896b63f7908297dfe7a48e198d7bce847e2804b8 Mon Sep 17 00:00:00 2001 From: Jim Procter Date: Mon, 13 Sep 2021 16:02:02 +0100 Subject: [PATCH] JAL-3829 select single best TDB structure and select structures from particular provider (this code is horrific !) --- src/jalview/gui/StructureChooser.java | 39 ++++- .../StructureChooserQuerySource.java | 9 +- .../gui/structurechooser/TDBResultAnalyser.java | 33 ++++- .../ThreeDBStructureChooserQuerySource.java | 153 ++++++++++++++------ src/jalview/jbgui/FilterOption.java | 29 +++- 5 files changed, 203 insertions(+), 60 deletions(-) diff --git a/src/jalview/gui/StructureChooser.java b/src/jalview/gui/StructureChooser.java index 864f1d0..6bcac24 100644 --- a/src/jalview/gui/StructureChooser.java +++ b/src/jalview/gui/StructureChooser.java @@ -97,6 +97,8 @@ public class StructureChooser extends GStructureChooser private boolean cachedPDBExists; + private Collection lastDiscoveredStructuresSet; + private static StructureViewer lastTargetedView = null; public StructureChooser(SequenceI[] selectedSeqs, SequenceI selectedSeq, @@ -280,7 +282,9 @@ public class StructureChooser extends GStructureChooser { getResultTable() .setModel(data.getTableModel(discoveredStructuresSet)); + noOfStructuresFound = discoveredStructuresSet.size(); + lastDiscoveredStructuresSet=discoveredStructuresSet; mainFrame.setTitle(MessageManager.formatMessage( "label.structure_chooser_no_of_structures", noOfStructuresFound, totalTime)); @@ -336,6 +340,7 @@ public class StructureChooser extends GStructureChooser { Thread filterThread = new Thread(new Runnable() { + @Override public void run() { @@ -378,7 +383,7 @@ public class StructureChooser extends GStructureChooser reorderedStructuresSet.addAll(discoveredStructuresSet); getResultTable() .setModel(data.getTableModel(reorderedStructuresSet)); - + FTSRestResponse.configureTableColumn(getResultTable(), wantedFields, tempUserPrefs); getResultTable().getColumn("Ref Sequence").setPreferredWidth(120); @@ -450,17 +455,33 @@ public class StructureChooser extends GStructureChooser protected void populateFilterComboBox(boolean haveData, boolean cachedPDBExist) { + populateFilterComboBox(haveData, cachedPDBExist, null); + } + /** + * Populates the filter combo-box options dynamically depending on discovered + * structures + */ + protected void populateFilterComboBox(boolean haveData, + boolean cachedPDBExist, FilterOption lastSel) + { + /* * temporarily suspend the change listener behaviour */ cmb_filterOption.removeItemListener(this); - + int selSet=-1; cmb_filterOption.removeAllItems(); if (haveData) { List filters = data.getAvailableFilterOptions(VIEWS_FILTER); + data.updateAvailableFilterOptions(VIEWS_FILTER, filters, lastDiscoveredStructuresSet); + int p=0; for (FilterOption filter:filters) { + if (lastSel!=null && filter.equals(lastSel)) { + selSet=p; + } + p++; cmb_filterOption.addItem(filter); } } @@ -477,9 +498,14 @@ public class StructureChooser extends GStructureChooser MessageManager.getString("label.cached_structures"), "-", VIEWS_LOCAL_PDB, false,null); cmb_filterOption.addItem(cachedOption); - cmb_filterOption.setSelectedItem(cachedOption); + if (selSet==-1) { + cmb_filterOption.setSelectedItem(cachedOption); + } + } + if (selSet>-1) + { + cmb_filterOption.setSelectedIndex(selSet); } - cmb_filterOption.addItemListener(this); } @@ -498,7 +524,8 @@ public class StructureChooser extends GStructureChooser if (selectedFilterOpt.getView() == VIEWS_FILTER) { mainFrame.setTitle(filterTitle); - chk_invertFilter.setVisible(true); + // TDB Query has no invert as yet + chk_invertFilter.setVisible(selectedFilterOpt.getQuerySource() instanceof PDBStructureChooserQuerySource); if (data!=selectedFilterOpt.getQuerySource() || data.needsRefetch(selectedFilterOpt)) { @@ -1074,6 +1101,8 @@ public class StructureChooser extends GStructureChooser public void run() { fetchStructuresMetaData(); + //populateFilterComboBox(true, cachedPDBExists); + filterResultSet( ((FilterOption) cmb_filterOption.getSelectedItem()) .getValue()); diff --git a/src/jalview/gui/structurechooser/StructureChooserQuerySource.java b/src/jalview/gui/structurechooser/StructureChooserQuerySource.java index c18a8a2..b5646db 100644 --- a/src/jalview/gui/structurechooser/StructureChooserQuerySource.java +++ b/src/jalview/gui/structurechooser/StructureChooserQuerySource.java @@ -245,4 +245,11 @@ public abstract class StructureChooserQuerySource */ public abstract boolean needsRefetch(FilterOption selectedFilterOpt); -} \ No newline at end of file + + + public void updateAvailableFilterOptions(String VIEWS_FILTER, + List xtantOptions, Collection lastFTSData) + { + // TODO Auto-generated method stub + + }} \ No newline at end of file diff --git a/src/jalview/gui/structurechooser/TDBResultAnalyser.java b/src/jalview/gui/structurechooser/TDBResultAnalyser.java index cf3cc0c..06dbe2d 100644 --- a/src/jalview/gui/structurechooser/TDBResultAnalyser.java +++ b/src/jalview/gui/structurechooser/TDBResultAnalyser.java @@ -42,16 +42,30 @@ public class TDBResultAnalyser private int idx_resol; + /** + * selection model + */ + private String filter=null; + /** + * limit to particular source + */ + private String sourceFilter=null; + + private int idx_mprov; + public TDBResultAnalyser(SequenceI seq, Collection collectedResults, - FTSRestRequest lastTdbRequest) + FTSRestRequest lastTdbRequest, String fieldToFilterBy, String string) { this.seq = seq; this.collectedResults = collectedResults; this.lastTdbRequest = lastTdbRequest; + this.filter = fieldToFilterBy; + this.sourceFilter = string; idx_ups = lastTdbRequest.getFieldIndex("Uniprot Start"); idx_upe = lastTdbRequest.getFieldIndex("Uniprot End"); idx_mcat = lastTdbRequest.getFieldIndex("Model Category"); + idx_mprov = lastTdbRequest.getFieldIndex("Provider"); idx_mqual = lastTdbRequest.getFieldIndex("Confidence"); idx_resol = lastTdbRequest.getFieldIndex("Resolution"); } @@ -81,19 +95,20 @@ public class TDBResultAnalyser { int up_s = (Integer) row.getSummaryData()[idx_ups]; int up_e = (Integer) row.getSummaryData()[idx_upe]; - - if (seq == row.getSummaryData()[0] && up_e > seq.getStart() - && up_s < seq.getEnd()) + String provider = (String) row.getSummaryData()[idx_mprov]; + if (sourceFilter == null || sourceFilter.equals(provider)) { - filteredResponse.add(row); + if (seq == row.getSummaryData()[0] && up_e > seq.getStart() + && up_s < seq.getEnd()) + { + filteredResponse.add(row); + } } } // sort according to decreasing length, // increasing start Collections.sort(filteredResponse, new Comparator() { - - @Override public int compare(FTSData o1, FTSData o2) { @@ -197,6 +212,10 @@ public class TDBResultAnalyser return o2_xt-o1_xt; } }); + if (filter.equals(ThreeDBStructureChooserQuerySource.FILTER_FIRST_BEST_COVERAGE)) + { + return selected.subList(0, 1); + } return selected; } diff --git a/src/jalview/gui/structurechooser/ThreeDBStructureChooserQuerySource.java b/src/jalview/gui/structurechooser/ThreeDBStructureChooserQuerySource.java index d64d643..d465e23 100644 --- a/src/jalview/gui/structurechooser/ThreeDBStructureChooserQuerySource.java +++ b/src/jalview/gui/structurechooser/ThreeDBStructureChooserQuerySource.java @@ -36,7 +36,13 @@ public class ThreeDBStructureChooserQuerySource extends StructureChooserQuerySource { - private static final String FILTER_TDBEACONS_COVERAGE = "3d_beacons_coverage"; + private Set tdBeaconsFilters = null, defaultFilters = null; + + public static final String FILTER_TDBEACONS_COVERAGE = "3d_beacons_coverage"; + + public static final String FILTER_FIRST_BEST_COVERAGE = "3d_beacons_first_best_coverage"; + + private static final String FILTER_SOURCE_PREFIX = "only_"; private static int MAX_QLENGTH = 7820; @@ -48,12 +54,15 @@ public class ThreeDBStructureChooserQuerySource public ThreeDBStructureChooserQuerySource() { + defaultFilters = new LinkedHashSet(); + defaultFilters.add(FILTER_TDBEACONS_COVERAGE); + defaultFilters.add(FILTER_FIRST_BEST_COVERAGE); + tdbRestClient = TDBeaconsFTSRestClient.getInstance(); docFieldPrefs = new FTSDataColumnPreferences( PreferenceSource.STRUCTURE_CHOOSER, TDBeaconsFTSRestClient.getInstance()); - - } + } /** * Builds a query string for a given sequences using its DBRef entries 3d @@ -155,30 +164,34 @@ public class ThreeDBStructureChooserQuerySource FilterOption selectedFilterOpt, boolean b) throws Exception { FTSRestResponse resultList; - if (tdBeaconsFilter(selectedFilterOpt.getValue())) { - FTSRestRequest tdbRequest = getTDBeaconsRequest(seq, wantedFields); - resultList = tdbRestClient.executeRequest(tdbRequest); - - lastTdbRequest = tdbRequest; - - // Query the PDB and add additional metadata - FTSRestResponse pdbResponse = fetchStructuresMetaDataFor(getPDBQuerySource(), resultList); - FTSRestResponse joinedResp = joinResponses(resultList, - pdbResponse); - return resultList; - } + if (selectedFilterOpt!=null && tdBeaconsFilter(selectedFilterOpt.getValue())) + { + FTSRestRequest tdbRequest = getTDBeaconsRequest(seq, wantedFields); + resultList = tdbRestClient.executeRequest(tdbRequest); + + lastTdbRequest = tdbRequest; + + // Query the PDB and add additional metadata + FTSRestResponse pdbResponse = fetchStructuresMetaDataFor( + getPDBQuerySource(), resultList); + FTSRestResponse joinedResp = joinResponses(resultList, pdbResponse); + return resultList; + } // use the PDBFTS directly - resultList = getPDBQuerySource().fetchStructuresMetaData(seq, wantedFields, selectedFilterOpt, b); + resultList = getPDBQuerySource().fetchStructuresMetaData(seq, + wantedFields, selectedFilterOpt, b); lastTdbRequest = getPDBQuerySource().lastPdbRequest; - lastPdbRequest = lastTdbRequest; // both queries the same - indicates we rank using PDBe + lastPdbRequest = lastTdbRequest; // both queries the same - indicates we + // rank using PDBe return resultList; - + } - PDBStructureChooserQuerySource pdbQuerySource=null; + PDBStructureChooserQuerySource pdbQuerySource = null; + private PDBStructureChooserQuerySource getPDBQuerySource() { - if (pdbQuerySource==null) + if (pdbQuerySource == null) { pdbQuerySource = new PDBStructureChooserQuerySource(); } @@ -205,23 +218,71 @@ public class ThreeDBStructureChooserQuerySource @Override public List getAvailableFilterOptions(String VIEWS_FILTER) { - List filters = getPDBQuerySource().getAvailableFilterOptions(VIEWS_FILTER); - - filters.add(0, - new FilterOption("3D-Beacons Coverage", - FILTER_TDBEACONS_COVERAGE, VIEWS_FILTER, true, this)); + List filters = getPDBQuerySource() + .getAvailableFilterOptions(VIEWS_FILTER); + tdBeaconsFilters = new LinkedHashSet(); + tdBeaconsFilters.addAll(defaultFilters); + filters.add(0, new FilterOption("Best 3D-Beacons Coverage", + FILTER_FIRST_BEST_COVERAGE, VIEWS_FILTER, false, this)); + filters.add(1, new FilterOption("Multiple 3D-Beacons Coverage", + FILTER_TDBEACONS_COVERAGE, VIEWS_FILTER, true, this)); + return filters; } + + @Override + public void updateAvailableFilterOptions(String VIEWS_FILTER, + List xtantOptions, Collection tdbEntries) + { + if (tdbEntries !=null && lastTdbRequest != null) + { + int prov_idx = lastTdbRequest.getFieldIndex("Provider"); + + 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); + if (!xtantOptions.contains(providerOpt)) + { + xtantOptions.add(1, + providerOpt); + tdBeaconsFilters.add(FILTER_SOURCE_PREFIX+provider); + + } + } + } + + } + private boolean tdBeaconsFilter(String fieldToFilterBy) { - return FILTER_TDBEACONS_COVERAGE.equals(fieldToFilterBy); + return tdBeaconsFilters != null + && tdBeaconsFilters.contains(fieldToFilterBy); + } + + private String remove_prefix(String fieldToFilterBy) + { + if (tdBeaconsFilters != null + && tdBeaconsFilters.contains(fieldToFilterBy) + && !defaultFilters.contains(fieldToFilterBy)) + { + return fieldToFilterBy.substring(FILTER_SOURCE_PREFIX.length()); + } + else + { + return null; + } } @Override public boolean needsRefetch(FilterOption selectedFilterOpt) { - return tdBeaconsFilter(selectedFilterOpt.getValue()) && lastPdbRequest!=lastTdbRequest; + return selectedFilterOpt==null || !tdBeaconsFilter(selectedFilterOpt.getValue()) + && lastPdbRequest != lastTdbRequest; } + /** * FTSRestClient specific query builder to pick top ranked entry from a * fetchStructuresMetaData query @@ -242,10 +303,11 @@ public class ThreeDBStructureChooserQuerySource Collection wantedFields, String fieldToFilterBy, boolean b) throws Exception { - if (tdBeaconsFilter(fieldToFilterBy)) + if (fieldToFilterBy!=null && tdBeaconsFilter(fieldToFilterBy)) { TDBResultAnalyser analyser = new TDBResultAnalyser(seq, - collectedResults, lastTdbRequest); + collectedResults, lastTdbRequest, fieldToFilterBy, + remove_prefix(fieldToFilterBy)); FTSRestResponse resultList = new FTSRestResponse(); @@ -258,10 +320,10 @@ public class ThreeDBStructureChooserQuerySource return resultList; } // Fall back to PDBe rankings - return getPDBQuerySource().selectFirstRankedQuery(seq, collectedResults, wantedFields, fieldToFilterBy, b); + return getPDBQuerySource().selectFirstRankedQuery(seq, collectedResults, + wantedFields, fieldToFilterBy, b); } - @Override public PDBEntry[] collectSelectedRows(JTable restable, int[] selectedRows, List selectedSeqsToView) @@ -275,29 +337,32 @@ public class ThreeDBStructureChooserQuerySource int typeColumnIndex = restable.getColumn("Provider").getModelIndex(); int categoryColumnIndex = restable.getColumn("Model Category") .getModelIndex(); - final int up_start_idx = restable.getColumn("Uniprot Start").getModelIndex(); - final int up_end_idx = restable.getColumn("Uniprot End").getModelIndex(); - int i=0; - + final int up_start_idx = restable.getColumn("Uniprot Start") + .getModelIndex(); + final int up_end_idx = restable.getColumn("Uniprot End") + .getModelIndex(); + int i = 0; + // bleugh! Integer[] sellist = new Integer[selectedRows.length]; - for (Integer row: selectedRows) + for (Integer row : selectedRows) { sellist[i++] = row; } // Sort rows by coverage - Arrays.sort(sellist,new Comparator() + Arrays.sort(sellist, new Comparator() { @Override public int compare(Integer o1, Integer o2) { - int o1_xt = ((Integer)restable.getValueAt(o1, up_end_idx)) - (Integer)restable.getValueAt(o1, up_start_idx); - int o2_xt = ((Integer)restable.getValueAt(o2, up_end_idx)) - (Integer)restable.getValueAt(o2, up_start_idx); - return o2_xt-o1_xt; + int o1_xt = ((Integer) restable.getValueAt(o1, up_end_idx)) + - (Integer) restable.getValueAt(o1, up_start_idx); + int o2_xt = ((Integer) restable.getValueAt(o2, up_end_idx)) + - (Integer) restable.getValueAt(o2, up_start_idx); + return o2_xt - o1_xt; } }); - for (int row : sellist) { // unique id - could be a horrible hash @@ -400,7 +465,7 @@ public class ThreeDBStructureChooserQuerySource int pdbIdx = lastPdbRequest.getFieldIndex("PDB Id"); int pdbTitle_idx = lastPdbRequest.getFieldIndex("Title"); int tdbTitle_idx = getLastFTSRequest().getFieldIndex("Title"); - + List joinedRows = new ArrayList(); for (final FTSData row : upResponse.getSearchSummary()) { @@ -417,7 +482,9 @@ public class ThreeDBStructureChooserQuerySource .getSummaryData()[pdbTitle_idx]; } } - } else { + } + else + { row.getSummaryData()[tdbTitle_idx] = "Model from TDB"; } } diff --git a/src/jalview/jbgui/FilterOption.java b/src/jalview/jbgui/FilterOption.java index d52dbbf..57a1a42 100644 --- a/src/jalview/jbgui/FilterOption.java +++ b/src/jalview/jbgui/FilterOption.java @@ -18,7 +18,7 @@ public class FilterOption private String view; private boolean addSeparatorAfter; - + private StructureChooserQuerySource querySource; /** @@ -33,15 +33,17 @@ public class FilterOption * @param addSeparatorAfter * - if true, a horizontal separator is rendered immediately after * this filter option, otherwise - * @param structureChooserQuerySource - the query source that actions this filter + * @param structureChooserQuerySource + * - the query source that actions this filter */ public FilterOption(String name, String value, String view, - boolean addSeparatorAfter, StructureChooserQuerySource structureChooserQuerySource) + boolean addSeparatorAfter, + StructureChooserQuerySource structureChooserQuerySource) { this.name = name; this.value = value; this.view = view; - this.querySource=structureChooserQuerySource; + this.querySource = structureChooserQuerySource; this.addSeparatorAfter = addSeparatorAfter; } @@ -95,4 +97,23 @@ public class FilterOption { return querySource; } + + @Override + public boolean equals(Object obj) + { + if (obj instanceof FilterOption) { + FilterOption o=(FilterOption) obj; + return o.name.equals(name) && o.querySource==querySource && o.value.equals(value) && o.view==view; + } else { + return super.equals(obj); + } + } + + @Override + public int hashCode() + { + return ("" + name + ":" + value).hashCode() + + (view != null ? view.hashCode() : 0) + + (querySource != null ? querySource.hashCode() : 0); + } } \ No newline at end of file -- 1.7.10.2