X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fgui%2FStructureViewer.java;h=b1426136edfd8e591c8d8ab4de61204c7db78301;hb=f8b17a9e7363b8a9e7cd12d61bc6d611c7c97d7d;hp=9a13b5e702423693cf05bbfc9bc7685b24cfab4a;hpb=838e4f91d4a53dd315640dbc9ff6ef7a815ee576;p=jalview.git diff --git a/src/jalview/gui/StructureViewer.java b/src/jalview/gui/StructureViewer.java index 9a13b5e..b142613 100644 --- a/src/jalview/gui/StructureViewer.java +++ b/src/jalview/gui/StructureViewer.java @@ -1,6 +1,6 @@ /* - * Jalview - A Sequence Alignment Editor and Viewer (Version 2.9.0b1) - * Copyright (C) 2015 The Jalview Authors + * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$) + * Copyright (C) $$Year-Rel$$ The Jalview Authors * * This file is part of Jalview. * @@ -29,19 +29,24 @@ import jalview.structure.StructureSelectionManager; import java.awt.Rectangle; import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; +import java.util.Map.Entry; /** - * proxy for handling structure viewers. - * - * this allows new views to be created with the currently configured viewer, the - * preferred viewer to be set/read and existing views created previously with a - * particular viewer to be recovered + * A proxy for handling structure viewers, that orchestrates adding selected + * structures, associated with sequences in Jalview, to an existing viewer, or + * opening a new one. Currently supports either Jmol or Chimera as the structure + * viewer. * * @author jprocter */ public class StructureViewer { + private static final String UNKNOWN_VIEWER_TYPE = "Unknown structure viewer type "; + StructureSelectionManager ssm; public enum ViewerType @@ -49,6 +54,16 @@ public class StructureViewer JMOL, CHIMERA }; + /** + * Constructor + * + * @param structureSelectionManager + */ + public StructureViewer(StructureSelectionManager structureSelectionManager) + { + ssm = structureSelectionManager; + } + public ViewerType getViewerType() { String viewType = Cache.getDefault(Preferences.STRUCTURE_DISPLAY, @@ -61,28 +76,112 @@ public class StructureViewer Cache.setProperty(Preferences.STRUCTURE_DISPLAY, type.name()); } - public StructureViewer(StructureSelectionManager structureSelectionManager) - { - ssm = structureSelectionManager; - } - /** * View multiple PDB entries, each with associated sequences * * @param pdbs - * @param seqsForPdbs + * @param seqs * @param ap * @return */ public JalviewStructureDisplayI viewStructures(PDBEntry[] pdbs, - SequenceI[][] seqsForPdbs, AlignmentPanel ap) + SequenceI[] seqs, AlignmentPanel ap) { - JalviewStructureDisplayI viewer = onlyOnePdb(pdbs, seqsForPdbs, ap); + JalviewStructureDisplayI viewer = onlyOnePdb(pdbs, seqs, ap); if (viewer != null) { + /* + * user added structure to an existing viewer - all done + */ return viewer; } - return viewStructures(getViewerType(), pdbs, seqsForPdbs, ap); + + ViewerType viewerType = getViewerType(); + + Map seqsForPdbs = getSequencesForPdbs(pdbs, + seqs); + PDBEntry[] pdbsForFile = seqsForPdbs.keySet().toArray( + new PDBEntry[seqsForPdbs.size()]); + SequenceI[][] theSeqs = seqsForPdbs.values().toArray( + new SequenceI[seqsForPdbs.size()][]); + JalviewStructureDisplayI sview = null; + if (viewerType.equals(ViewerType.JMOL)) + { + sview = new AppJmol(ap, pdbsForFile, theSeqs); + } + else if (viewerType.equals(ViewerType.CHIMERA)) + { + sview = new ChimeraViewFrame(pdbsForFile, theSeqs, ap); + } + else + { + Cache.log.error(UNKNOWN_VIEWER_TYPE + getViewerType().toString()); + } + return sview; + } + + /** + * Converts the list of selected PDB entries (possibly including duplicates + * for multiple chains), and corresponding sequences, into a map of sequences + * for each distinct PDB file. Returns null if either argument is null, or + * their lengths do not match. + * + * @param pdbs + * @param seqs + * @return + */ + Map getSequencesForPdbs(PDBEntry[] pdbs, + SequenceI[] seqs) + { + if (pdbs == null || seqs == null || pdbs.length != seqs.length) + { + return null; + } + + /* + * we want only one 'representative' PDBEntry per distinct file name + * (there may be entries for distinct chains) + */ + Map pdbsSeen = new HashMap<>(); + + /* + * LinkedHashMap preserves order of PDB entries (significant if they + * will get superimposed to the first structure) + */ + Map> pdbSeqs = new LinkedHashMap<>(); + for (int i = 0; i < pdbs.length; i++) + { + PDBEntry pdb = pdbs[i]; + SequenceI seq = seqs[i]; + String pdbFile = pdb.getFile(); + if (!pdbsSeen.containsKey(pdbFile)) + { + pdbsSeen.put(pdbFile, pdb); + pdbSeqs.put(pdb, new ArrayList()); + } + else + { + pdb = pdbsSeen.get(pdbFile); + } + List seqsForPdb = pdbSeqs.get(pdb); + if (!seqsForPdb.contains(seq)) + { + seqsForPdb.add(seq); + } + } + + /* + * convert to Map + */ + Map result = new LinkedHashMap<>(); + for (Entry> entry : pdbSeqs.entrySet()) + { + List theSeqs = entry.getValue(); + result.put(entry.getKey(), + theSeqs.toArray(new SequenceI[theSeqs.size()])); + } + + return result; } /** @@ -98,7 +197,7 @@ public class StructureViewer * @return */ private JalviewStructureDisplayI onlyOnePdb(PDBEntry[] pdbs, - SequenceI[][] seqsForPdbs, AlignmentPanel ap) + SequenceI[] seqsForPdbs, AlignmentPanel ap) { List seqs = new ArrayList(); if (pdbs == null || pdbs.length == 0) @@ -114,48 +213,20 @@ public class StructureViewer { return null; } - SequenceI[] pdbseqs = seqsForPdbs[i++]; - if (pdbseqs != null) + SequenceI pdbseq = seqsForPdbs[i++]; + if (pdbseq != null) { - for (SequenceI sq : pdbseqs) - { - seqs.add(sq); - } + seqs.add(pdbseq); } } - return viewStructures(pdbs[0], - seqs.toArray(new SequenceI[seqs.size()]), ap); + return viewStructures(pdbs[0], seqs.toArray(new SequenceI[seqs.size()]), + ap); } public JalviewStructureDisplayI viewStructures(PDBEntry pdb, SequenceI[] seqsForPdb, AlignmentPanel ap) { - return viewStructures(getViewerType(), pdb, seqsForPdb, ap); - } - - protected JalviewStructureDisplayI viewStructures(ViewerType viewerType, - PDBEntry[] pdbs, SequenceI[][] seqsForPdbs, AlignmentPanel ap) - { - JalviewStructureDisplayI sview = null; - if (viewerType.equals(ViewerType.JMOL)) - { - sview = new AppJmol(ap, pdbs, ap.av.collateForPDB(pdbs)); - } - else if (viewerType.equals(ViewerType.CHIMERA)) - { - sview = new ChimeraViewFrame(pdbs, ap.av.collateForPDB(pdbs), ap); - } - else - { - Cache.log.error("Unknown structure viewer type " - + getViewerType().toString()); - } - return sview; - } - - protected JalviewStructureDisplayI viewStructures(ViewerType viewerType, - PDBEntry pdb, SequenceI[] seqsForPdb, AlignmentPanel ap) - { + ViewerType viewerType = getViewerType(); JalviewStructureDisplayI sview = null; if (viewerType.equals(ViewerType.JMOL)) { @@ -167,8 +238,7 @@ public class StructureViewer } else { - Cache.log.error("Unknown structure viewer type " - + getViewerType().toString()); + Cache.log.error(UNKNOWN_VIEWER_TYPE + getViewerType().toString()); } return sview; } @@ -187,10 +257,10 @@ public class StructureViewer * @param vid * @return */ - public JalviewStructureDisplayI createView(ViewerType type, - String[] pdbf, String[] id, SequenceI[][] sq, - AlignmentPanel alignPanel, StructureViewerModel viewerData, - String fileloc, Rectangle rect, String vid) + public JalviewStructureDisplayI createView(ViewerType type, String[] pdbf, + String[] id, SequenceI[][] sq, AlignmentPanel alignPanel, + StructureViewerModel viewerData, String fileloc, Rectangle rect, + String vid) { final boolean useinViewerSuperpos = viewerData.isAlignWithPanel(); final boolean usetoColourbyseq = viewerData.isColourWithAlignPanel(); @@ -204,11 +274,11 @@ public class StructureViewer useinViewerSuperpos, viewerColouring, fileloc, rect, vid); break; case CHIMERA: - Cache.log.error("Unsupported structure viewer type " - + type.toString()); + Cache.log.error( + "Unsupported structure viewer type " + type.toString()); break; default: - Cache.log.error("Unknown structure viewer type " + type.toString()); + Cache.log.error(UNKNOWN_VIEWER_TYPE + type.toString()); } return sview; }