import jalview.structure.StructureMapping;
import jalview.structure.StructureMappingcommandSet;
import jalview.structure.StructureSelectionManager;
+import jalview.util.Comparison;
import java.awt.Color;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
+import java.util.List;
import java.util.Map;
/**
SequenceI[][] sequence, SequenceRenderer sr, FeatureRenderer fr,
AlignmentI alignment)
{
-
- ArrayList<StructureMappingcommandSet> cset = new ArrayList<StructureMappingcommandSet>();
+ String defAttrPath = null;
+ FileOutputStream fos = null;
+ try
+ {
+ File outFile = File.createTempFile("jalviewdefattr", ".xml");
+ outFile.deleteOnExit();
+ defAttrPath = outFile.getPath();
+ fos = new FileOutputStream(outFile);
+ fos.write("attribute: jalviewclr\n".getBytes());
+ } catch (IOException e1)
+ {
+ e1.printStackTrace();
+ }
+ List<StructureMappingcommandSet> cset = new ArrayList<StructureMappingcommandSet>();
/*
* Map of { colour, positionSpecs}
*/
Map<String, StringBuilder> colranges = new LinkedHashMap<String, StringBuilder>();
+ StringBuilder setAttributes = new StringBuilder(256);
+ String lastColour = "none";
+ Color lastCol = null;
for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
{
+ boolean startModel = true;
StructureMapping[] mapping = ssm.getMapping(files[pdbfnum]);
if (mapping == null || mapping.length < 1)
continue;
}
- int startPos = -1, lastPos = -1, startModel = -1, lastModel = -1;
+ int startPos = -1, lastPos = -1;
String lastChain = "";
- Color lastCol = null;
for (int s = 0; s < sequence[pdbfnum].length; s++)
{
for (int sp, m = 0; m < mapping.length; m++)
{
- if (mapping[m].getSequence() == sequence[pdbfnum][s]
- && (sp = alignment.findIndex(sequence[pdbfnum][s])) > -1)
+ final SequenceI seq = sequence[pdbfnum][s];
+ if (mapping[m].getSequence() == seq
+ && (sp = alignment.findIndex(seq)) > -1)
{
SequenceI asp = alignment.getSequenceAt(sp);
for (int r = 0; r < asp.getLength(); r++)
{
// no mapping to gaps in sequence
- if (jalview.util.Comparison.isGap(asp.getCharAt(r)))
+ if (Comparison.isGap(asp.getCharAt(r)))
{
continue;
}
continue;
}
- Color col = sr.getResidueBoxColour(sequence[pdbfnum][s], r);
-
- if (fr != null)
+ Color col = getResidueColour(seq, r, sr, fr);
+ /*
+ * 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 = !col.equals(lastCol);
+ final boolean nonContig = lastPos + 1 != pos;
+ final boolean newChain = !mapping[m].getChain().equals(lastChain);
+ if (newColour || nonContig || startModel || newChain)
{
- col = fr.findFeatureColour(col, sequence[pdbfnum][s], r);
- }
- if (lastCol != col || lastPos + 1 != pos
- || pdbfnum != lastModel
- || !mapping[m].getChain().equals(lastChain))
- {
- if (lastCol != null)
+ if (/* lastCol != null */startPos != -1)
{
- addColourRange(colranges, lastCol,startModel,startPos,lastPos,lastChain);
+ addColourRange(colranges, lastCol, pdbfnum, startPos,
+ lastPos, lastChain, startModel);
+ startModel = false;
}
- lastCol = null;
+ // lastCol = null;
startPos = pos;
- startModel = pdbfnum;
}
lastCol = col;
lastPos = pos;
- lastModel = pdbfnum;
+ // lastModel = pdbfnum;
lastChain = mapping[m].getChain();
}
// final colour range
if (lastCol != null)
{
- addColourRange(colranges, lastCol,startModel,startPos,lastPos,lastChain);
+ addColourRange(colranges, lastCol, pdbfnum, startPos,
+ lastPos, lastChain, false);
}
break;
}
}
}
- // Finally, add the command set ready to be returned.
- StringBuilder coms = new StringBuilder(256);
- for (String cr:colranges.keySet())
+ }
+ try
+ {
+ lastColour = buildColourCommands(cset, colranges,
+ fos, setAttributes);
+ } catch (IOException e)
{
- coms.append("color #"+cr+" "+colranges.get(cr)+";");
+ e.printStackTrace();
}
- cset.add(new StructureMappingcommandSet(ChimeraCommands.class,
- files[pdbfnum], new String[] { coms.toString() }));
+
+ try
+ {
+ fos.close();
+ } catch (IOException e)
+ {
+ e.printStackTrace();
+ }
+
+ /*
+ * Send a rangeColor command, preceded by either defattr or setattr,
+ * whichever we end up preferring!
+ *
+ * rangecolor requires a minimum of two attribute values to operate on
+ */
+ StringBuilder rangeColor = new StringBuilder(256);
+ rangeColor.append("rangecolor jalviewclr");
+ int colourId = 0;
+ for (String colour : colranges.keySet())
+ {
+ colourId++;
+ rangeColor.append(" " + colourId + " " + colour);
}
+ String rangeColorCommand = rangeColor.toString();
+ if (rangeColorCommand.split(" ").length < 5)
+ {
+ rangeColorCommand += " max " + lastColour;
+ }
+ final String defAttrCommand = "defattr " + defAttrPath
+ + " raiseTool false";
+ final String setAttrCommand = setAttributes.toString();
+ final String attrCommand = false ? defAttrCommand : setAttrCommand;
+ cset.add(new StructureMappingcommandSet(ChimeraCommands.class, null,
+ new String[]
+ { attrCommand /* , rangeColorCommand */}));
+
return cset.toArray(new StructureMappingcommandSet[cset.size()]);
}
/**
+ * Get the residue colour at the given sequence position - as determined by
+ * the sequence group colour (if any), else the colour scheme, possibly
+ * overridden by a feature colour.
+ *
+ * @param seq
+ * @param position
+ * @param sr
+ * @param fr
+ * @return
+ */
+ protected static Color getResidueColour(final SequenceI seq,
+ int position, SequenceRenderer sr, FeatureRenderer fr)
+ {
+ Color col = sr.getResidueBoxColour(seq, position);
+
+ if (fr != null)
+ {
+ col = fr.findFeatureColour(col, seq, position);
+ }
+ return col;
+ }
+
+ /**
+ * Helper method to build the colour commands for one PDBfile.
+ *
+ * @param cset
+ * the list of commands to be added to
+ * @param colranges
+ * the map of colours to residue positions already determined
+ * @param fos
+ * file to write 'defattr' commands to
+ * @param setAttributes
+ * @throws IOException
+ */
+ protected static String buildColourCommands(
+ List<StructureMappingcommandSet> cset,
+ Map<String, StringBuilder> colranges,
+ FileOutputStream fos, StringBuilder setAttributes)
+ throws IOException
+ {
+ int colourId = 0;
+ String lastColour = null;
+ for (String colour : colranges.keySet())
+ {
+ lastColour = colour;
+ colourId++;
+ /*
+ * Using color command directly is slow for larger structures.
+ * setAttributes.append("color #" + colour + " " + colranges.get(colour)+
+ * ";");
+ */
+ setAttributes.append("color " + colour + " " + colranges.get(colour)
+ + ";");
+ final String atomSpec = new String(colranges.get(colour));
+ // setAttributes.append("setattr r jalviewclr " + colourId + " "
+ // + atomSpec + ";");
+ fos.write(("\t" + atomSpec + "\t" + colourId + "\n").getBytes());
+ }
+ return lastColour;
+ }
+
+ /**
* Helper method to record a range of positions of the same colour.
*
* @param colranges
* @param startPos
* @param endPos
* @param chain
+ * @param changeModel
*/
private static void addColourRange(Map<String, StringBuilder> colranges,
- Color colour, int model,
- int startPos, int endPos, String chain)
+ Color colour, int model, int startPos, int endPos, String chain,
+ boolean startModel)
{
- String colstring = ((colour.getRed()< 16) ? "0":"")+Integer.toHexString(colour.getRed())
+ String colstring = "#" + ((colour.getRed() < 16) ? "0" : "")
+ + Integer.toHexString(colour.getRed())
+ ((colour.getGreen()< 16) ? "0":"")+Integer.toHexString(colour.getGreen())
+ ((colour.getBlue()< 16) ? "0":"")+Integer.toHexString(colour.getBlue());
StringBuilder currange = colranges.get(colstring);
{
colranges.put(colstring, currange = new StringBuilder(256));
}
- if (currange.length() > 0)
+ /*
+ * Format as (e.g.) #0:1-3.A,5.A,7-10.A,...#1:1-4.B,..etc
+ */
+ // if (currange.length() > 0)
+ // {
+ // currange.append("|");
+ // }
+ // currange.append("#" + model + ":" + ((startPos==endPos) ? startPos :
+ // startPos + "-"
+ // + endPos) + "." + chain);
+ if (currange.length() == 0)
+ {
+ currange.append("#" + model + ":");
+ }
+ else if (startModel)
+ {
+ currange.append(",#" + model + ":");
+ }
+ else
{
- currange.append("|");
+ currange.append(",");
}
- currange.append("#" + model + ":" + ((startPos==endPos) ? startPos : startPos + "-"
- + endPos) + "." + chain);
+ final String rangeSpec = (startPos == endPos) ? Integer
+ .toString(startPos) : (startPos + "-" + endPos);
+ currange.append(rangeSpec + "." + chain);
}
}