import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
+import java.util.Collections;
import java.util.HashMap;
+import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
private boolean finishedInit = false;
- /**
- * current set of model filenames loaded in the viewer
+ /*
+ * current set of model filenames loaded in the Jmol instance
+ * array index 0, 1, 2... corresponds to Jmol model numbers 1, 2, 3...
*/
protected String[] modelFileNames = null;
public String fileLoadingError;
+ private boolean showAlignmentOnly;
+
+ /*
+ * a list of chains "pdbid:chainid" to hide in the viewer
+ */
+ // TODO make private once deprecated JalviewJmolBinding.centerViewer removed
+ protected List<String> chainsToHide;
+
+ private boolean hideHiddenRegions;
+
/**
* Constructor
*
{
this.ssm = ssm;
this.sequence = seqs;
+ chainsToHide = new ArrayList<>();
chainNames = new ArrayList<>();
chainFile = new HashMap<>();
}
this.nucleotide = Comparison.isNucleotide(sequenceIs);
this.pdbEntry = pdbentry;
this.protocol = protocol;
+ chainsToHide = new ArrayList<>();
+
resolveChains();
}
/**
* Instruct the Jalview binding to update the pdbentries vector if necessary
- * prior to matching the jmol view's contents to the list of structure files
+ * prior to matching the viewer's contents to the list of structure files
* Jalview knows about. By default does nothing, override as required.
*/
public void refreshPdbEntries()
AlignmentViewPanel alignment);
/**
+ * Recolours mapped residues in the structure viewer to match colours in the
+ * given alignment panel, provided colourBySequence is selected. Colours
+ * should also be applied to any hidden mapped residues (so that they are
+ * shown correctly if these get unhidden).
+ *
+ * @param viewPanel
+ */
+ protected void colourBySequence(AlignmentViewPanel viewPanel)
+ {
+
+ if (!colourBySequence || !isLoadingFinished() || getSsm() == null)
+ {
+ return;
+ }
+ Map<Object, AtomSpecModel> colourMap = buildColoursMap(ssm, sequence,
+ viewPanel);
+
+ List<StructureCommandI> colourBySequenceCommands = commandGenerator
+ .colourBySequence(colourMap);
+ executeCommands(colourBySequenceCommands, false, null);
+
+ }
+
+ /**
* Sends a command to the structure viewer to colour each chain with a
* distinct colour (to the extent supported by the viewer)
*/
public void colourByChain()
{
colourBySequence = false;
-
// TODO: JAL-628 colour chains distinctly across all visible models
-
executeCommand(commandGenerator.colourByChain(), false,
COLOURING_STRUCTURES);
}
}
/**
- * Colours any structures associated with sequences in the given alignment as
- * coloured in the alignment view, provided colourBySequence is enabled
+ * Recolours the displayed structures, if they are coloured by
+ * sequence, or 'show only visible alignment' is selected. This supports
+ * updating structure colours on either change of alignment colours, or change
+ * to the visible region of the alignment.
*/
- public void colourBySequence(AlignmentViewPanel alignmentv)
+ public void updateStructureColours(AlignmentViewPanel alignmentv)
{
- if (!colourBySequence || !isLoadingFinished() || getSsm() == null)
+ if (!isLoadingFinished())
{
return;
}
- Map<Object, AtomSpecModel> colourMap = buildColoursMap(ssm, sequence,
- alignmentv);
- List<StructureCommandI> colourBySequenceCommands = commandGenerator
- .colourBySequence(colourMap);
- executeCommands(colourBySequenceCommands, false, null);
+ /*
+ * if structure is not coloured by sequence, but restricted to the alignment,
+ * then redraw it (but don't recolour it) in case hidden regions have changed
+ * (todo: specific messaging for change of hidden region only)
+ */
+ if (!colourBySequence)
+ {
+ if (isShowAlignmentOnly())
+ {
+ showStructures(alignmentv.getAlignViewport(), false);
+ }
+ return;
+ }
+ if (getSsm() == null)
+ {
+ return;
+ }
+ colourBySequence(alignmentv);
}
/**
}
/**
+ * Sets the flag for whether only mapped visible residues in the alignment
+ * should be visible in the structure viewer
+ *
+ * @param b
+ */
+ public void setShowAlignmentOnly(boolean b)
+ {
+ showAlignmentOnly = b;
+ }
+
+ /**
+ * Answers true if only residues mapped to the alignment should be shown in the
+ * structure viewer, else false
+ *
+ * @return
+ */
+ public boolean isShowAlignmentOnly()
+ {
+ return showAlignmentOnly;
+ }
+
+ /**
+ * Sets the flag for hiding regions of structure which are hidden in the
+ * alignment (only applies when the structure viewer is restricted to the
+ * alignment only)
+ *
+ * @param b
+ */
+ public void setHideHiddenRegions(boolean b)
+ {
+ hideHiddenRegions = b;
+ }
+
+ /**
+ * Answers true if regions hidden in the alignment should also be hidden in the
+ * structure viewer, else false (only applies when the structure viewer is
+ * restricted to the alignment only)
+ *
+ * @return
+ */
+ public boolean isHideHiddenRegions()
+ {
+ return hideHiddenRegions;
+ }
+
+ /**
+ * Shows the structures in the viewer, without changing their colouring. This is
+ * to support toggling of whether the whole structure is shown, or only residues
+ * mapped to visible regions of the alignment.
+ *
+ * @param alignViewportI
+ * @param refocus
+ * if true, refit the display to the viewer
+ */
+ public void showStructures(AlignViewportI alignViewportI, boolean refocus)
+ {
+ // override with implementation
+ }
+
+ /**
+ * Sets the list of chains to hide (as "pdbid:chain")
+ *
+ * @param chains
+ */
+ public void setChainsToHide(List<String> chains)
+ {
+ chainsToHide = chains;
+ }
+
+ /**
+ * Answers true if the specified structure and chain are selected to be shown in
+ * the viewer, else false
+ *
+ * @param pdbId
+ * @param chainId
+ * @return
+ */
+ protected boolean isShowChain(String pdbId, String chainId)
+ {
+ if (chainsToHide.isEmpty())
+ {
+ return true;
+ }
+ return !chainsToHide.contains(pdbId + ":" + chainId);
+ }
+
+ @Override
+ public abstract String[] getStructureFiles();
+
+ /**
+ * Builds a model of residues mapped from sequences to show on structure, taking
+ * into account user choices of
+ * <ul>
+ * <li>which chains are shown</li>
+ * <li>whether all structure is shown, or only that mapped to the alignment</li>
+ * <li>whether hidden regions of the alignment are hidden (excluded) or grayed
+ * out (included)</li>
+ * </ul>
+ *
+ * @param av
+ * @return
+ */
+ protected AtomSpecModel getShownResidues(AlignViewportI av)
+ {
+ AlignmentI alignment = av.getAlignment();
+ final int width = alignment.getWidth();
+
+ String[] files = getStructureFiles();
+
+ AtomSpecModel model = new AtomSpecModel();
+
+ for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
+ {
+ String fileName = files[pdbfnum];
+ final String modelId = getModelIdForFile(files[pdbfnum]);
+ StructureMapping[] mappings = getSsm().getMapping(fileName);
+
+ /*
+ * Find the first mapped sequence (if any) for this PDB entry which is in
+ * the alignment
+ */
+ final int seqCountForPdbFile = getSequence()[pdbfnum].length;
+ for (int s = 0; s < seqCountForPdbFile; s++)
+ {
+ for (StructureMapping mapping : mappings)
+ {
+ final SequenceI theSequence = getSequence()[pdbfnum][s];
+ if (mapping.getSequence() == theSequence
+ && alignment.findIndex(theSequence) > -1)
+ {
+ String chainCd = mapping.getChain();
+ if (!isShowChain(mapping.getPdbId(), chainCd))
+ {
+ // continue;
+ }
+ Iterator<int[]> visible;
+ if (isShowAlignmentOnly() && isHideHiddenRegions())
+ {
+ visible = alignment.getHiddenColumns()
+ .getVisContigsIterator(0, width, true);
+ }
+ else
+ {
+ visible = Collections.singletonList(new int[] { 0, width })
+ .iterator();
+ }
+ while (visible.hasNext())
+ {
+ int[] visibleRegion = visible.next();
+ int seqStartPos = theSequence.findPosition(visibleRegion[0]);
+ int seqEndPos = theSequence.findPosition(visibleRegion[1]);
+ List<int[]> residueRanges = mapping
+ .getPDBResNumRanges(seqStartPos, seqEndPos);
+ if (!residueRanges.isEmpty())
+ {
+ for (int[] range : residueRanges)
+ {
+ model.addRange(modelId, range[0], range[1], chainCd);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return model;
+ }
+
+ /**
+ * Answers the structure viewer's model number for the given PDB file, or -1 if
+ * not found
+ *
+ * @param fileName
+ * @param fileIndex
+ * index of the file in the stored array of file names
+ * @return
+ */
+ public int getModelForPdbFile(String fileName, int fileIndex)
+ {
+ return fileIndex;
+ }
+
+ /**
+ * Answers a default structure model specification which is simply the string
+ * form of the model number. Override if needed to specify submodels.
+ *
+ * @param model
+ * @return
+ */
+ public String getModelSpec(int model)
+ {
+ return String.valueOf(model);
+ }
+
+ /**
* Returns the FeatureRenderer for the given alignment view, or null if
* feature display is turned off in the view.
*
}
if (!isLoadingFromArchive())
{
- colourBySequence(ap);
+ updateStructureColours(ap);
}
}