+
+ /**
+ * 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
+ */
+ protected 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.addMapRange(colourMap, lastColour,
+ pdbfnum, startPos,
+ lastPos, lastChain);
+ }
+ startPos = pos;
+ }
+ lastColour = colour;
+ lastPos = pos;
+ lastChain = chain;
+ }
+ // final colour range
+ if (lastColour != null)
+ {
+ ChimeraCommands.addMapRange(colourMap, lastColour, pdbfnum,
+ startPos, lastPos, lastChain);
+ }
+ // break;
+ }
+ }
+ }
+ }
+ return colourMap;
+ }