import java.awt.Color;
import java.util.ArrayList;
-import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
SequenceI[][] sequence, SequenceRenderer sr, FeatureRenderer fr,
AlignmentI alignment)
{
- Map<Color, AtomSpecModel> colourMap = buildColoursMap(
+ Map<Object, AtomSpecModel> colourMap = buildColoursMap(
ssm, files, sequence, sr, fr, alignment);
List<String> colourCommands = buildColourCommands(colourMap);
* @return
*/
protected static List<String> buildColourCommands(
- Map<Color, AtomSpecModel> colourMap)
+ Map<Object, AtomSpecModel> colourMap)
{
/*
* This version concatenates all commands into a single String (semi-colon
List<String> commands = new ArrayList<String>();
StringBuilder sb = new StringBuilder(256);
boolean firstColour = true;
- for (Color colour : colourMap.keySet())
+ for (Object key : colourMap.keySet())
{
+ Color colour = (Color) key;
String colourCode = ColorUtils.toTkCode(colour);
if (!firstColour)
{
* Ordering is by order of addition (for colours and positions), natural ordering (for models and chains)
* </pre>
*/
- protected static Map<Color, AtomSpecModel> buildColoursMap(
+ protected static Map<Object, AtomSpecModel> buildColoursMap(
StructureSelectionManager ssm, String[] files,
SequenceI[][] sequence, SequenceRenderer sr, FeatureRenderer fr,
AlignmentI alignment)
{
- Map<Color, AtomSpecModel> colourMap = new LinkedHashMap<Color, AtomSpecModel>();
+ Map<Object, AtomSpecModel> colourMap = new LinkedHashMap<Object, AtomSpecModel>();
Color lastColour = null;
for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
{
{
if (startPos != -1)
{
- addColourRange(colourMap, lastColour, pdbfnum, startPos,
+ addRange(colourMap, lastColour, pdbfnum, startPos,
lastPos, lastChain);
}
startPos = pos;
// final colour range
if (lastColour != null)
{
- addColourRange(colourMap, lastColour, pdbfnum, startPos,
+ addRange(colourMap, lastColour, pdbfnum, startPos,
lastPos, lastChain);
}
// break;
/**
* Helper method to add one contiguous colour range to the colour map.
*
- * @param colourMap
- * @param colour
+ * @param map
+ * @param key
* @param model
* @param startPos
* @param endPos
* @param chain
*/
- protected static void addColourRange(
-Map<Color, AtomSpecModel> colourMap,
- Color colour, int model, int startPos, int endPos, String chain)
+ protected static void addRange(Map<Object, AtomSpecModel> map,
+ Object key, int model, int startPos, int endPos, String chain)
{
- // refactor for reuse as addRange
/*
* Get/initialize map of data for the colour
*/
- AtomSpecModel colourData = colourMap.get(colour);
- if (colourData == null)
+ AtomSpecModel atomSpec = map.get(key);
+ if (atomSpec == null)
{
- colourData = new AtomSpecModel();
- colourMap.put(colour, colourData);
+ atomSpec = new AtomSpecModel();
+ map.put(key, atomSpec);
}
- colourData.addRange(model, startPos, endPos, chain);
+ atomSpec.addRange(model, startPos, endPos, chain);
}
/**
* Constructs and returns a set of Chimera commands to set attributes on
- * residues corresponding to features in Jalview.
+ * residues corresponding to features in Jalview
*
* @param ssm
* @param files
StructureSelectionManager ssm, String[] files,
SequenceI[][] seqs, FeatureRenderer fr, AlignmentI alignment)
{
- Map<String, Map<Integer, Map<String, List<int[]>>>> featureMap = buildFeaturesMap(
+ Map<String, AtomSpecModel> featureMap = buildFeaturesMap(
ssm, files, seqs, fr, alignment);
- List<String> colourCommands = buildSetAttributeCommands(featureMap);
+ List<String> commands = buildSetAttributeCommands(featureMap);
StructureMappingcommandSet cs = new StructureMappingcommandSet(
ChimeraCommands.class, null,
- colourCommands.toArray(new String[colourCommands.size()]));
+ commands.toArray(new String[commands.size()]));
return cs;
}
/**
- * <pre>
- * Helper method to build a map of
- * { featureType, {modelNumber, {chain, {list of from-to ranges} } } }
- * </pre>
+ * Helper method to build a map of { featureType, AtomSpecModel }
*
* @param ssm
* @param files
* @param alignment
* @return
*/
- protected static Map<String, Map<Integer, Map<String, List<int[]>>>> buildFeaturesMap(
+ protected static Map<String, AtomSpecModel> buildFeaturesMap(
StructureSelectionManager ssm, String[] files,
SequenceI[][] seqs, FeatureRenderer fr, AlignmentI alignment)
{
- Map<String, Map<Integer, Map<String, List<int[]>>>> theMap = new HashMap<String, Map<Integer, Map<String, List<int[]>>>>();
+ Map<String, AtomSpecModel> theMap = new LinkedHashMap<String, AtomSpecModel>();
List<String> visibleFeatures = fr.getDisplayedFeatureTypes();
if (visibleFeatures.isEmpty())
return theMap;
}
- /*
- * traverse mappings to structures
- */
for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
{
StructureMapping[] mapping = ssm.getMapping(files[pdbfnum]);
continue;
}
- int lastPos = -1;
for (int seqNo = 0; seqNo < seqs[pdbfnum].length; seqNo++)
{
for (int m = 0; m < mapping.length; m++)
int sp = alignment.findIndex(seq);
if (mapping[m].getSequence() == seq && sp > -1)
{
- SequenceI asp = alignment.getSequenceAt(sp);
-
/*
- * traverse each sequence for its mapped positions
+ * found a sequence with a mapping to a structure;
+ * now scan its features
*/
- for (int r = 0; r < asp.getLength(); r++)
- {
- // no mapping to gaps in sequence
- if (Comparison.isGap(asp.getCharAt(r)))
- {
- continue;
- }
- int residuePos = asp.findPosition(r);
- int pos = mapping[m].getPDBResNum(residuePos);
-
- if (pos < 1 || pos == lastPos)
- {
- continue;
- }
- final String chain = mapping[m].getChain();
+ SequenceI asp = alignment.getSequenceAt(sp);
- /*
- * record any features at this position, with the model, chain
- * and residue number they map to
- */
- List<SequenceFeature> features = fr.findFeaturesAtRes(asp,
- residuePos);
- for (SequenceFeature feature : features)
- {
- if (!visibleFeatures.contains(feature))
- {
- continue;
- }
- }
- }
+ scanSequenceFeatures(visibleFeatures, mapping[m], asp, theMap,
+ pdbfnum);
}
}
}
- }
+ }
return theMap;
}
/**
+ * Inspect features on the sequence; for each feature that is visible,
+ * determine its mapped ranges in the structure (if any) according to the
+ * given mapping, and add them to the map
+ *
+ * @param visibleFeatures
+ * @param mapping
+ * @param seq
+ * @param theMap
+ * @param modelNumber
+ */
+ protected static void scanSequenceFeatures(List<String> visibleFeatures,
+ StructureMapping mapping, SequenceI seq,
+ Map<String, AtomSpecModel> theMap, int modelNumber)
+ {
+ SequenceFeature[] sfs = seq.getSequenceFeatures();
+ if (sfs == null)
+ {
+ return;
+ }
+
+ for (SequenceFeature sf : sfs)
+ {
+ String type = sf.getType();
+ if (!visibleFeatures.contains(type))
+ {
+ continue;
+ }
+ List<int[]> mappedRanges = mapping.getPDBResNumRanges(sf.getBegin(),
+ sf.getEnd());
+
+ if (!mappedRanges.isEmpty())
+ {
+ AtomSpecModel atomSpec = theMap.get(type);
+ if (atomSpec == null)
+ {
+ atomSpec = new AtomSpecModel();
+ theMap.put(type, atomSpec);
+ }
+ for (int[] range : mappedRanges)
+ {
+ atomSpec.addRange(modelNumber, range[0], range[1],
+ mapping.getChain());
+ }
+ }
+ }
+ }
+
+ /**
* Traverse the map of features/models/chains/positions to construct a list of
* 'setattr' commands (one per feature type). The format of each command is
*
*
* @param featureMap
* @return
- * @see http
- * ://www.cgl.ucsf.edu/chimera/current/docs/UsersGuide/midas/frameatom_spec
- * .html
*/
protected static List<String> buildSetAttributeCommands(
- Map<String, Map<Integer, Map<String, List<int[]>>>> featureMap)
+ Map<String, AtomSpecModel> featureMap)
{
List<String> commands = new ArrayList<String>();
for (String featureType : featureMap.keySet())
{
StringBuilder sb = new StringBuilder(128);
- featureType = featureType.replace(" ", "_");
- sb.append("setattr r jv:").append(featureType).append(" \" \" ");
- final Map<Integer, Map<String, List<int[]>>> featureData = featureMap
- .get(featureType);
- sb.append(getAtomSpec(featureData));
+ String sanitised = featureType.replace(" ", "_").replace("-", "_");
+ sb.append("setattr r jv_").append(sanitised).append(" \" \" ");
+ sb.append(featureMap.get(featureType).getAtomSpec());
commands.add(sb.toString());
}
public void testBuildColourCommands()
{
- Map<Color, AtomSpecModel> map = new LinkedHashMap<Color, AtomSpecModel>();
- ChimeraCommands.addColourRange(map, Color.blue, 0, 2, 5, "A");
- ChimeraCommands.addColourRange(map, Color.blue, 0, 7, 7, "B");
- ChimeraCommands.addColourRange(map, Color.blue, 0, 9, 23, "A");
- ChimeraCommands.addColourRange(map, Color.blue, 1, 1, 1, "A");
- ChimeraCommands.addColourRange(map, Color.blue, 1, 4, 7, "B");
- ChimeraCommands.addColourRange(map, Color.yellow, 1, 8, 8, "A");
- ChimeraCommands.addColourRange(map, Color.yellow, 1, 3, 5, "A");
- ChimeraCommands.addColourRange(map, Color.red, 0, 3, 5, "A");
- ChimeraCommands.addColourRange(map, Color.red, 0, 6, 9, "A");
+ Map<Object, AtomSpecModel> map = new LinkedHashMap<Object, AtomSpecModel>();
+ ChimeraCommands.addRange(map, Color.blue, 0, 2, 5, "A");
+ ChimeraCommands.addRange(map, Color.blue, 0, 7, 7, "B");
+ ChimeraCommands.addRange(map, Color.blue, 0, 9, 23, "A");
+ ChimeraCommands.addRange(map, Color.blue, 1, 1, 1, "A");
+ ChimeraCommands.addRange(map, Color.blue, 1, 4, 7, "B");
+ ChimeraCommands.addRange(map, Color.yellow, 1, 8, 8, "A");
+ ChimeraCommands.addRange(map, Color.yellow, 1, 3, 5, "A");
+ ChimeraCommands.addRange(map, Color.red, 0, 3, 5, "A");
+ ChimeraCommands.addRange(map, Color.red, 0, 6, 9, "A");
// Colours should appear in the Chimera command in the order in which
// they were added; within colour, by model, by chain, ranges in start order