X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fstructure%2FStructureSelectionManager.java;h=3194cce2f5f516bf08b6e4cbbf5d10061ad186f6;hb=7e3a6674abdd31bf48e7e249a74eff50fd2ce589;hp=10fe8367ab150de89a10275f725134d56b14f27f;hpb=f8202652aae8b6b41c796a84b7a9ef15eba22bb9;p=jalview.git diff --git a/src/jalview/structure/StructureSelectionManager.java b/src/jalview/structure/StructureSelectionManager.java index 10fe836..3194cce 100644 --- a/src/jalview/structure/StructureSelectionManager.java +++ b/src/jalview/structure/StructureSelectionManager.java @@ -20,8 +20,21 @@ */ package jalview.structure; +import java.io.PrintStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.IdentityHashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Vector; + import jalview.analysis.AlignSeq; import jalview.api.StructureSelectionManagerProvider; +import jalview.bin.Console; import jalview.commands.CommandI; import jalview.commands.EditCommand; import jalview.commands.OrderCommand; @@ -29,6 +42,7 @@ import jalview.datamodel.AlignedCodonFrame; import jalview.datamodel.AlignmentAnnotation; import jalview.datamodel.AlignmentI; import jalview.datamodel.Annotation; +import jalview.datamodel.ContiguousI; import jalview.datamodel.HiddenColumns; import jalview.datamodel.PDBEntry; import jalview.datamodel.SearchResults; @@ -39,26 +53,16 @@ import jalview.gui.IProgressIndicator; import jalview.io.AppletFormatAdapter; import jalview.io.DataSourceType; import jalview.io.StructureFile; +import jalview.structure.StructureImportSettings.TFType; import jalview.util.MappingUtils; import jalview.util.MessageManager; +import jalview.util.Platform; import jalview.ws.sifts.SiftsClient; import jalview.ws.sifts.SiftsException; import jalview.ws.sifts.SiftsSettings; - -import java.io.PrintStream; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.IdentityHashMap; -import java.util.List; -import java.util.Map; -import java.util.Vector; - -import MCview.Atom; -import MCview.PDBChain; -import MCview.PDBfile; +import mc_view.Atom; +import mc_view.PDBChain; +import mc_view.PDBfile; public class StructureSelectionManager { @@ -285,7 +289,8 @@ public class StructureSelectionManager } /** - * Returns the file name for a mapped PDB id (or null if not mapped). + * Returns the filename the PDB id is already mapped to if known, or null if + * it is not mapped * * @param pdbid * @return @@ -294,7 +299,7 @@ public class StructureSelectionManager { for (StructureMapping sm : mappings) { - if (sm.getPdbId().equals(pdbid)) + if (sm.getPdbId().equalsIgnoreCase(pdbid)) { return sm.pdbfile; } @@ -318,11 +323,11 @@ public class StructureSelectionManager * @return null or the structure data parsed as a pdb file */ synchronized public StructureFile setMapping(SequenceI[] sequence, - String[] targetChains, String pdbFile, DataSourceType protocol, + String[] targetChains, String pdbFile, DataSourceType protocol, IProgressIndicator progress) { return computeMapping(true, sequence, targetChains, pdbFile, protocol, - progress); + progress, null, null); } /** @@ -345,10 +350,11 @@ public class StructureSelectionManager */ synchronized public StructureFile setMapping(boolean forStructureView, SequenceI[] sequenceArray, String[] targetChainIds, - String pdbFile, DataSourceType sourceType) + String pdbFile, DataSourceType sourceType, TFType tft, + String paeFilename) { return computeMapping(forStructureView, sequenceArray, targetChainIds, - pdbFile, sourceType, null); + pdbFile, sourceType, null, tft, paeFilename); } /** @@ -375,10 +381,10 @@ public class StructureSelectionManager * mapping operation * @return null or the structure data parsed as a pdb file */ - synchronized public StructureFile computeMapping( - boolean forStructureView, SequenceI[] sequenceArray, - String[] targetChainIds, String pdbFile, DataSourceType sourceType, - IProgressIndicator progress) + synchronized public StructureFile computeMapping(boolean forStructureView, + SequenceI[] sequenceArray, String[] targetChainIds, + String pdbFile, DataSourceType sourceType, + IProgressIndicator progress, TFType tft, String paeFilename) { long progressSessionId = System.currentTimeMillis() * 3; @@ -397,15 +403,36 @@ public class StructureSelectionManager { // FIXME if sourceType is not null, we've lost data here sourceType = AppletFormatAdapter.checkProtocol(pdbFile); - pdb = new JmolParser(pdbFile, sourceType); - + pdb = new JmolParser(false, pdbFile, sourceType); + if (paeFilename != null) + { + pdb.setPAEMatrix(paeFilename); + } + pdb.setTemperatureFactorType(tft); + pdb.addSettings(parseSecStr && processSecondaryStructure, + parseSecStr && addTempFacAnnot, + parseSecStr && secStructServices); + pdb.doParse(); if (pdb.getId() != null && pdb.getId().trim().length() > 0 && DataSourceType.FILE == sourceType) { registerPDBFile(pdb.getId().trim(), pdbFile); } // if PDBId is unavailable then skip SIFTS mapping execution path - isMapUsingSIFTs = isMapUsingSIFTs && pdb.isPPDBIdAvailable(); + // TODO: JAL-3868 need to know if structure is actually from + // PDB (has valid PDB ID and has provenance suggesting it + // actually came from PDB) + boolean isProtein = false; + for (SequenceI s : sequenceArray) + { + if (s.isProtein()) + { + isProtein = true; + break; + } + } + isMapUsingSIFTs = isMapUsingSIFTs && pdb.isPPDBIdAvailable() + && !pdb.getId().startsWith("AF-") && isProtein; } catch (Exception ex) { @@ -425,7 +452,8 @@ public class StructureSelectionManager } catch (SiftsException e) { isMapUsingSIFTs = false; - e.printStackTrace(); + Console.error("SIFTS mapping failed", e); + Console.error("Falling back on Needleman & Wunsch alignment"); siftsClient = null; } @@ -516,9 +544,11 @@ public class StructureSelectionManager List seqToStrucMapping = new ArrayList<>(); if (isMapUsingSIFTs && seq.isProtein()) { - if (progress!=null) { - progress.setProgressBar(MessageManager - .getString("status.obtaining_mapping_with_sifts"), + if (progress != null) + { + progress.setProgressBar( + MessageManager + .getString("status.obtaining_mapping_with_sifts"), progressSessionId); } jalview.datamodel.Mapping sqmpping = maxAlignseq @@ -532,22 +562,23 @@ public class StructureSelectionManager pdb, maxChain, sqmpping, maxAlignseq, siftsClient); seqToStrucMapping.add(siftsMapping); maxChain.makeExactMapping(siftsMapping, seq); - maxChain.transferRESNUMFeatures(seq, "IEA: SIFTS");// FIXME: is this - // "IEA:SIFTS" ? + maxChain.transferRESNUMFeatures(seq, "IEA: SIFTS", + pdb.getId().toLowerCase(Locale.ROOT)); maxChain.transferResidueAnnotation(siftsMapping, null); ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0)); } catch (SiftsException e) { // fall back to NW alignment - System.err.println(e.getMessage()); + Console.error(e.getMessage()); StructureMapping nwMapping = getNWMappings(seq, pdbFile, targetChainId, maxChain, pdb, maxAlignseq); seqToStrucMapping.add(nwMapping); maxChain.makeExactMapping(maxAlignseq, seq); - maxChain.transferRESNUMFeatures(seq, "IEA:Jalview"); // FIXME: is - // this - // "IEA:Jalview" ? + maxChain.transferRESNUMFeatures(seq, "IEA:Jalview", + pdb.getId().toLowerCase(Locale.ROOT)); // FIXME: is + // this + // "IEA:Jalview" ? maxChain.transferResidueAnnotation(nwMapping, sqmpping); ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0)); } @@ -560,17 +591,22 @@ public class StructureSelectionManager StructureMapping siftsMapping = null; try { - siftsMapping = getStructureMapping(seq, - pdbFile, chain.id, pdb, chain, sqmpping, maxAlignseq, - siftsClient); + siftsMapping = getStructureMapping(seq, pdbFile, chain.id, + pdb, chain, sqmpping, maxAlignseq, siftsClient); foundSiftsMappings.add(siftsMapping); chain.makeExactMapping(siftsMapping, seq); - chain.transferRESNUMFeatures(seq, "IEA: SIFTS");// FIXME: is this + chain.transferRESNUMFeatures(seq, "IEA: SIFTS", + pdb.getId().toLowerCase(Locale.ROOT));// FIXME: is this // "IEA:SIFTS" ? chain.transferResidueAnnotation(siftsMapping, null); } catch (SiftsException e) { System.err.println(e.getMessage()); + } catch (Exception e) + { + System.err.println( + "Unexpected exception during SIFTS mapping - falling back to NW for this sequence/structure pair"); + System.err.println(e.getMessage()); } } if (!foundSiftsMappings.isEmpty()) @@ -583,8 +619,9 @@ public class StructureSelectionManager StructureMapping nwMapping = getNWMappings(seq, pdbFile, maxChainId, maxChain, pdb, maxAlignseq); seqToStrucMapping.add(nwMapping); - maxChain.transferRESNUMFeatures(seq, null); // FIXME: is this - // "IEA:Jalview" ? + maxChain.transferRESNUMFeatures(seq, null, + pdb.getId().toLowerCase(Locale.ROOT)); // FIXME: is this + // "IEA:Jalview" ? maxChain.transferResidueAnnotation(nwMapping, sqmpping); ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0)); } @@ -594,8 +631,9 @@ public class StructureSelectionManager { if (progress != null) { - progress.setProgressBar(MessageManager - .getString("status.obtaining_mapping_with_nw_alignment"), + progress.setProgressBar( + MessageManager.getString( + "status.obtaining_mapping_with_nw_alignment"), progressSessionId); } StructureMapping nwMapping = getNWMappings(seq, pdbFile, maxChainId, @@ -605,7 +643,10 @@ public class StructureSelectionManager } if (forStructureView) { - mappings.addAll(seqToStrucMapping); + for (StructureMapping sm : seqToStrucMapping) + { + addStructureMapping(sm); // not addAll! + } } if (progress != null) { @@ -657,7 +698,10 @@ public class StructureSelectionManager public void addStructureMapping(StructureMapping sm) { - mappings.add(sm); + if (!mappings.contains(sm)) + { + mappings.add(sm); + } } /** @@ -679,7 +723,8 @@ public class StructureSelectionManager private StructureMapping getStructureMapping(SequenceI seq, String pdbFile, String targetChainId, StructureFile pdb, PDBChain maxChain, jalview.datamodel.Mapping sqmpping, - AlignSeq maxAlignseq, SiftsClient siftsClient) throws SiftsException + AlignSeq maxAlignseq, SiftsClient siftsClient) + throws SiftsException { StructureMapping curChainMapping = siftsClient .getSiftsStructureMapping(seq, pdbFile, targetChainId); @@ -745,7 +790,8 @@ public class StructureSelectionManager maxChain.makeExactMapping(maxAlignseq, seq); jalview.datamodel.Mapping sqmpping = maxAlignseq .getMappingFromS1(false); - maxChain.transferRESNUMFeatures(seq, null); + maxChain.transferRESNUMFeatures(seq, null, + pdb.getId().toLowerCase(Locale.ROOT)); HashMap mapping = new HashMap<>(); int resNum = -10000; @@ -836,18 +882,65 @@ public class StructureSelectionManager } /** + * hack to highlight a range of positions at once on any structure views + * + * @param sequenceRef + * @param is + * - series of int start-end ranges as positions on sequenceRef + * @param i + * @param object + */ + public void highlightPositionsOn(SequenceI sequenceRef, int[][] is, + Object source) + { + boolean hasSequenceListeners = handlingVamsasMo + || !seqmappings.isEmpty(); + SearchResultsI results = null; + ArrayList listOfPositions = new ArrayList(); + for (int[] s_e : is) + { + for (int p = s_e[0]; p <= s_e[1]; listOfPositions.add(p++)) + ; + } + int seqpos[] = new int[listOfPositions.size()]; + int i = 0; + for (Integer p : listOfPositions) + { + seqpos[i++] = p; + } + + for (i = 0; i < listeners.size(); i++) + { + Object listener = listeners.elementAt(i); + if (listener == source) + { + // TODO listener (e.g. SeqPanel) is never == source (AlignViewport) + // Temporary fudge with SequenceListener.getVamsasSource() + continue; + } + if (listener instanceof StructureListener) + { + highlightStructure((StructureListener) listener, sequenceRef, + seqpos); + } + + } + } + + /** * Propagate mouseover of a single position in a structure * * @param pdbResNum * @param chain * @param pdbfile + * @return */ - public void mouseOverStructure(int pdbResNum, String chain, + public String mouseOverStructure(int pdbResNum, String chain, String pdbfile) { AtomSpec atomSpec = new AtomSpec(pdbfile, chain, pdbResNum, 0); List atoms = Collections.singletonList(atomSpec); - mouseOverStructure(atoms); + return mouseOverStructure(atoms); } /** @@ -855,12 +948,12 @@ public class StructureSelectionManager * * @param atoms */ - public void mouseOverStructure(List atoms) + public String mouseOverStructure(List atoms) { if (listeners == null) { // old or prematurely sent event - return; + return null; } boolean hasSequenceListener = false; for (int i = 0; i < listeners.size(); i++) @@ -872,18 +965,24 @@ public class StructureSelectionManager } if (!hasSequenceListener) { - return; + return null; } SearchResultsI results = findAlignmentPositionsForStructurePositions( atoms); + String result = null; for (Object li : listeners) { if (li instanceof SequenceListener) { - ((SequenceListener) li).highlightSequence(results); + String s = ((SequenceListener) li).highlightSequence(results); + if (s != null) + { + result = s; + } } } + return result; } /** @@ -1038,6 +1137,62 @@ public class StructureSelectionManager sl.highlightAtoms(atoms); } + public void highlightStructureRegionsFor(StructureListener sl, + SequenceI[] seqs, int... columns) + { + List to_highlight = new ArrayList(); + for (SequenceI seq : seqs) + { + if (sl.isListeningFor(seq)) + { + to_highlight.add(seq); + } + } + if (to_highlight.size() == 0) + { + return; + } + List atoms = new ArrayList<>(); + for (SequenceI seq : to_highlight) + { + int atomNo; + for (StructureMapping sm : mappings) + { + if (sm.sequence == seq || sm.sequence == seq.getDatasetSequence() + || (sm.sequence.getDatasetSequence() != null && sm.sequence + .getDatasetSequence() == seq.getDatasetSequence())) + { + + for (int i = 0; i < columns.length; i += 2) + { + ContiguousI positions = seq.findPositions(columns[i] + 1, + columns[i + 1] + 1); + if (positions == null) + { + continue; + } + for (int index = positions.getBegin(); index <= positions + .getEnd(); index++) + { + + atomNo = sm.getAtomNum(index); + + if (atomNo > 0) + { + atoms.add(new AtomSpec(sm.pdbfile, sm.pdbchain, + sm.getPDBResNum(index), atomNo)); + } + } + } + } + } + if (atoms.size() > 0) + { + sl.highlightAtoms(atoms); + } + } + } + /** * true if a mouse over event from an external (ie Vamsas) source is being * handled @@ -1153,7 +1308,8 @@ public class StructureSelectionManager StringBuilder sb = new StringBuilder(64); for (StructureMapping sm : mappings) { - if (sm.pdbfile.equals(pdbfile) && seqs.contains(sm.sequence)) + if (Platform.pathEquals(sm.pdbfile, pdbfile) + && seqs.contains(sm.sequence)) { sb.append(sm.mappingDetails); sb.append(NEWLINE); @@ -1326,7 +1482,10 @@ public class StructureSelectionManager instances.remove(jalviewLite); try { - mnger.finalize(); + /* bsoares 2019-03-20 finalize deprecated, no apparent external + * resources to close + */ + // mnger.finalize(); } catch (Throwable x) { } @@ -1412,4 +1571,44 @@ public class StructureSelectionManager return seqmappings; } + /** + * quick and dirty route to just highlight all structure positions for a range + * of columns + * + * @param sequencesArray + * @param is + * start-end columns on sequencesArray + * @param source + * origin parent AlignmentPanel + */ + public void highlightPositionsOnMany(SequenceI[] sequencesArray, int[] is, + Object source) + { + for (int i = 0; i < listeners.size(); i++) + { + Object listener = listeners.elementAt(i); + if (listener == source) + { + // TODO listener (e.g. SeqPanel) is never == source (AlignViewport) + // Temporary fudge with SequenceListener.getVamsasSource() + continue; + } + if (listener instanceof StructureListener) + { + highlightStructureRegionsFor((StructureListener) listener, + sequencesArray, is); + } + } + } + + public Map getPdbFileNameIdMap() + { + return pdbFileNameId; + } + + public Map getPdbIdFileNameMap() + { + return pdbIdFileName; + } + }