import jalview.api.AlignViewportI;
import jalview.api.AlignmentViewPanel;
+import jalview.api.FeatureRenderer;
import jalview.api.SequenceRenderer;
import jalview.api.StructureSelectionManagerProvider;
import jalview.api.structures.JalviewStructureDisplayI;
import jalview.datamodel.PDBEntry;
import jalview.datamodel.SequenceI;
import jalview.ext.rbvi.chimera.AtomSpecModel;
+import jalview.ext.rbvi.chimera.ChimeraCommands;
import jalview.io.DataSourceType;
+import jalview.renderer.seqfeatures.FeatureColourFinder;
import jalview.schemes.ColourSchemeI;
import jalview.structure.AtomSpec;
import jalview.structure.StructureListener;
import jalview.structure.StructureMapping;
-import jalview.structure.StructureMappingcommandSet;
import jalview.structure.StructureSelectionManager;
import jalview.util.Comparison;
import jalview.util.MessageManager;
import java.util.BitSet;
import java.util.Collections;
import java.util.Iterator;
+import java.util.LinkedHashMap;
import java.util.List;
+import java.util.Map;
/**
*
* a list of chains "pdbid:chainid" to show in the viewer;
* empty means show all
*/
- // TODO make private once showStructures() deals with this
+ // TODO make private once deprecated JalviewJmolBinding.centerViewer removed
protected List<String> chainsToShow;
private boolean hideHiddenRegions;
+ protected List<String> chainNames = new ArrayList<>();
+
/**
* Data bean class to simplify parameterisation in superposeStructures
*/
}
/**
- * Returns a list of chains mapped in this viewer.
- *
- * @return
- */
- public abstract List<String> getChainNames();
-
- /**
* Returns the Jalview panel hosting the structure viewer (if any)
*
* @return
public abstract void setBackgroundColour(Color col);
- protected abstract StructureMappingcommandSet[] getColourBySequenceCommands(
+ protected abstract String[] getColourBySequenceCommands(
String[] files, AlignmentViewPanel avp);
/**
AlignmentViewPanel alignment);
protected abstract void colourBySequence(
- StructureMappingcommandSet[] colourBySequenceCommands);
+ String[] colourBySequenceCommands);
public abstract void colourByChain();
* 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 (!isLoadingFinished())
{
}
String[] files = getStructureFiles();
- StructureMappingcommandSet[] colourBySequenceCommands = getColourBySequenceCommands(
+ String[] colourBySequenceCommands = getColourBySequenceCommands(
files, alignmentv);
colourBySequence(colourBySequenceCommands);
}
}
if (!isLoadingFromArchive())
{
- colourBySequence(ap);
+ updateStructureColours(ap);
}
}
{
return String.valueOf(model);
}
+
+ /**
+ * Build a data structure which records contiguous subsequences for each colour.
+ * From this we can easily generate the Chimera command for colour by sequence.
+ *
+ * <pre>
+ * Color
+ * Model number
+ * Chain
+ * list of start/end ranges
+ * </pre>
+ *
+ * Ordering is by order of addition (for colours and positions), natural
+ * ordering (for models and chains)
+ *
+ * @param viewPanel
+ * @return
+ */
+ public Map<Object, AtomSpecModel> buildColoursMap(
+ AlignmentViewPanel viewPanel)
+ {
+ FeatureRenderer fr = viewPanel.getFeatureRenderer();
+ FeatureColourFinder finder = new FeatureColourFinder(fr);
+ AlignViewportI viewport = viewPanel.getAlignViewport();
+ HiddenColumns cs = viewport.getAlignment().getHiddenColumns();
+ AlignmentI al = viewport.getAlignment();
+ SequenceRenderer sr = getSequenceRenderer(viewPanel);
+ String[] files = getStructureFiles();
+
+ Map<Object, AtomSpecModel> colourMap = new LinkedHashMap<>();
+ Color lastColour = null;
+
+ for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
+ {
+ StructureMapping[] mapping = ssm.getMapping(files[pdbfnum]);
+
+ if (mapping == null || mapping.length < 1)
+ {
+ continue;
+ }
+
+ int startPos = -1, lastPos = -1;
+ String lastChain = "";
+ for (int s = 0; s < sequence[pdbfnum].length; s++)
+ {
+ for (int sp, m = 0; m < mapping.length; m++)
+ {
+ final SequenceI seq = sequence[pdbfnum][s];
+ if (mapping[m].getSequence() == seq
+ && (sp = al.findIndex(seq)) > -1)
+ {
+ SequenceI asp = al.getSequenceAt(sp);
+ for (int r = 0; r < asp.getLength(); r++)
+ {
+ // no mapping to gaps in sequence
+ if (Comparison.isGap(asp.getCharAt(r)))
+ {
+ continue;
+ }
+ int pos = mapping[m].getPDBResNum(asp.findPosition(r));
+
+ if (pos < 1 || pos == lastPos)
+ {
+ continue;
+ }
+
+ Color colour = sr.getResidueColour(seq, r, finder);
+
+ /*
+ * hidden regions are shown gray or, optionally, ignored
+ */
+ if (!cs.isVisible(r))
+ {
+ if (hideHiddenRegions)
+ {
+ continue;
+ }
+ else
+ {
+ colour = Color.GRAY;
+ }
+ }
+
+ final String chain = mapping[m].getChain();
+
+ /*
+ * Just keep incrementing the end position for this colour range
+ * _unless_ colour, PDB model or chain has changed, or there is a
+ * gap in the mapped residue sequence
+ */
+ final boolean newColour = !colour.equals(lastColour);
+ final boolean nonContig = lastPos + 1 != pos;
+ final boolean newChain = !chain.equals(lastChain);
+ if (newColour || nonContig || newChain)
+ {
+ if (startPos != -1)
+ {
+ ChimeraCommands.addAtomSpecRange(colourMap, lastColour,
+ pdbfnum, startPos,
+ lastPos, lastChain);
+ }
+ startPos = pos;
+ }
+ lastColour = colour;
+ lastPos = pos;
+ lastChain = chain;
+ }
+ // final colour range
+ if (lastColour != null)
+ {
+ ChimeraCommands.addAtomSpecRange(colourMap, lastColour,
+ pdbfnum,
+ startPos, lastPos, lastChain);
+ }
+ // break;
+ }
+ }
+ }
+ }
+ return colourMap;
+ }
+
+ /**
+ * Returns a list of chains mapped in this viewer. Note this list is not
+ * currently scoped per structure.
+ *
+ * @return
+ */
+ public List<String> getChainNames()
+ {
+ return chainNames;
+ }
}