import jalview.datamodel.PDBEntry;
import jalview.datamodel.SequenceI;
import jalview.ext.rbvi.chimera.AtomSpecModel;
+import jalview.ext.rbvi.chimera.StructureCommands;
import jalview.gui.IProgressIndicator;
import jalview.io.DataSourceType;
import jalview.io.StructureFile;
}
// System.out.println("Select regions:\n" + selectioncom.toString());
evalStateCommand("select *; cartoons off; backbone; select ("
- + selectioncom.toString() + "); cartoons; ");
+ + selectioncom.toString() + "); cartoons; zoom 0");
// evalStateCommand("select *; backbone; select "+selcom.toString()+";
// cartoons; center "+selcom.toString());
}
protected String[] getColourBySequenceCommands(
String[] files, AlignmentViewPanel viewPanel)
{
- Map<Object, AtomSpecModel> map = buildColoursMap(viewPanel);
+ Map<Object, AtomSpecModel> map = StructureCommands.buildColoursMap(this, viewPanel);
return JmolCommands.getColourBySequenceCommand(map);
}
public void showStructures(AlignViewportI av, boolean refocus)
{
StringBuilder cmd = new StringBuilder(128);
-
if (isShowAlignmentOnly())
{
- cmd.append("hide *;");
-
AtomSpecModel model = getShownResidues(av);
String atomSpec = JmolCommands.getAtomSpec(model);
- cmd.append("display ").append(atomSpec);
+ cmd.append("hide *;display ").append(atomSpec)
+ .append("; select displayed");
}
else
{
- cmd.append("display *");
+ cmd.append(";display *");
}
- cmd.append("; cartoon");
+ cmd.append("; cartoon only");
if (refocus)
{
cmd.append("; zoom 0");
import jalview.datamodel.HiddenColumns;
import jalview.datamodel.SequenceI;
import jalview.ext.rbvi.chimera.AtomSpecModel;
+import jalview.ext.rbvi.chimera.StructureCommands;
import jalview.renderer.seqfeatures.FeatureColourFinder;
import jalview.structure.StructureMapping;
import jalview.structure.StructureMappingcommandSet;
import java.util.Map;
/**
- * Routines for generating Jmol commands for Jalview/Jmol binding another
- * cruisecontrol test.
+ * Routines for generating Jmol commands for Jalview/Jmol binding
*
* @author JimP
*
*/
-public class JmolCommands
+public class JmolCommands extends StructureCommands
{
-
private static final String COMMA = ",";
/**
sb.append(COMMA);
}
boolean firstRange = true;
- for (int[] range : atomSpecModel.getRanges(model, chain))
+
+ List<int[]> rangeList = atomSpecModel.getRanges(model, chain);
+
+ if (rangeList.size() > 1)
{
- if (!firstRange)
- {
- sb.append(COMMA);
- }
- firstRange = false;
- sb.append(range[0]);
- if (range[1] != range[0])
- {
- sb.append("-").append(range[1]);
- }
+ sb.append("(");
+ }
+ appendResidueRange(sb, rangeList, null, firstRange);
+ if (rangeList.size() > 1)
+ {
+ sb.append(")&");
}
- sb.append(":").append(chain).append("/")
+ sb.append(":").append(chain.trim()).append("/")
.append(String.valueOf(model + 1))
.append(".1");
}
import jalview.api.AlignViewportI;
import jalview.api.AlignmentViewPanel;
import jalview.api.FeatureRenderer;
-import jalview.api.SequenceRenderer;
import jalview.datamodel.AlignmentI;
-import jalview.datamodel.HiddenColumns;
import jalview.datamodel.MappedFeatures;
import jalview.datamodel.SequenceFeature;
import jalview.datamodel.SequenceI;
import jalview.gui.Desktop;
-import jalview.renderer.seqfeatures.FeatureColourFinder;
import jalview.structure.StructureMapping;
import jalview.structure.StructureMappingcommandSet;
import jalview.structure.StructureSelectionManager;
import jalview.structures.models.AAStructureBindingModel;
import jalview.util.ColorUtils;
-import jalview.util.Comparison;
-import jalview.util.IntRangeComparator;
import java.awt.Color;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.HashMap;
-import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
* @author JimP
*
*/
-public class ChimeraCommands
+public class ChimeraCommands extends StructureCommands
{
public static final String NAMESPACE_PREFIX = "jv_";
}
/**
- * 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 ssm
- * @param files
- * @param sequence
- * @param sr
- * @param hideHiddenRegions
- * @param viewPanel
- * @return
- */
- protected static Map<Object, AtomSpecModel> buildColoursMap(
- StructureSelectionManager ssm, String[] files,
- SequenceI[][] sequence, SequenceRenderer sr,
- boolean hideHiddenRegions, AlignmentViewPanel viewPanel)
- {
- FeatureRenderer fr = viewPanel.getFeatureRenderer();
- FeatureColourFinder finder = new FeatureColourFinder(fr);
- AlignViewportI viewport = viewPanel.getAlignViewport();
- HiddenColumns cs = viewport.getAlignment().getHiddenColumns();
- AlignmentI al = viewport.getAlignment();
- 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)
- {
- addAtomSpecRange(colourMap, lastColour, pdbfnum, startPos,
- lastPos, lastChain);
- }
- startPos = pos;
- }
- lastColour = colour;
- lastPos = pos;
- lastChain = chain;
- }
- // final colour range
- if (lastColour != null)
- {
- addAtomSpecRange(colourMap, lastColour, pdbfnum, startPos,
- lastPos, lastChain);
- }
- // break;
- }
- }
- }
- }
- return colourMap;
- }
-
- /**
- * Helper method to add one contiguous range to the AtomSpec model for the given
- * value (creating the model if necessary). As used by Jalview, {@code value} is
- * <ul>
- * <li>a colour, when building a 'colour structure by sequence' command</li>
- * <li>a feature value, when building a 'set Chimera attributes from features'
- * command</li>
- * </ul>
- *
- * @param map
- * @param value
- * @param model
- * @param startPos
- * @param endPos
- * @param chain
- */
- public static void addAtomSpecRange(Map<Object, AtomSpecModel> map,
- Object value, int model, int startPos, int endPos, String chain)
- {
- /*
- * Get/initialize map of data for the colour
- */
- AtomSpecModel atomSpec = map.get(value);
- if (atomSpec == null)
- {
- atomSpec = new AtomSpecModel();
- map.put(value, atomSpec);
- }
-
- atomSpec.addRange(model, startPos, endPos, chain);
- }
-
- /**
* Constructs and returns Chimera commands to set attributes on residues
* corresponding to features in Jalview. Attribute names are the Jalview feature
* type, with a "jv_" prefix.
sb.append("|");
}
firstModel = false;
- // todo use JalviewChimeraBinding.getModelSpec(model)
- // which means this cannot be static
sb.append(binding.getModelSpec(model)).append(":");
boolean firstPositionForModel = true;
List<int[]> rangeList = atomSpec.getRanges(model, chain);
- /*
- * sort ranges into ascending start position order
- */
- Collections.sort(rangeList, IntRangeComparator.ASCENDING);
-
- int start = rangeList.isEmpty() ? 0 : rangeList.get(0)[0];
- int end = rangeList.isEmpty() ? 0 : rangeList.get(0)[1];
-
- Iterator<int[]> iterator = rangeList.iterator();
- while (iterator.hasNext())
- {
- int[] range = iterator.next();
- if (range[0] <= end + 1)
- {
- /*
- * range overlaps or is contiguous with the last one
- * - so just extend the end position, and carry on
- * (unless this is the last in the list)
- */
- end = Math.max(end, range[1]);
- }
- else
- {
- /*
- * we have a break so append the last range
- */
- appendRange(sb, start, end, chain, firstPositionForModel);
- firstPositionForModel = false;
- start = range[0];
- end = range[1];
- }
- }
-
- /*
- * and append the last range
- */
- if (!rangeList.isEmpty())
- {
- appendRange(sb, start, end, chain, firstPositionForModel);
- firstPositionForModel = false;
- }
+ String chainToken = " ".equals(chain) ? "." : "." + chain;
+ appendResidueRange(sb, rangeList, chainToken,
+ firstPositionForModel);
+ firstPositionForModel = false;
}
}
return sb.toString();
}
/**
- * A helper method that appends one start-end range to a Chimera atomspec
+ * Chimera atomspec requires chain to be specified for each start-end residue
+ * range, otherwise it will apply to all chains
*
* @param sb
- * @param start
- * @param end
* @param chain
- * @param firstPositionForModel
*/
- static void appendRange(StringBuilder sb, int start, int end,
- String chain, boolean firstPositionForModel)
+ protected static void appendChainToRange(StringBuilder sb, String chain)
{
- if (!firstPositionForModel)
- {
- sb.append(",");
- }
- if (end == start)
- {
- sb.append(start);
- }
- else
- {
- sb.append(start).append("-").append(end);
- }
-
sb.append(".");
if (!" ".equals(chain))
{
protected String[] getColourBySequenceCommands(
String[] files, AlignmentViewPanel viewPanel)
{
- Map<Object, AtomSpecModel> colourMap = buildColoursMap(viewPanel);
+ Map<Object, AtomSpecModel> colourMap = StructureCommands.buildColoursMap(this, viewPanel);
return ChimeraCommands.getColourBySequenceCommand(colourMap, this);
}
--- /dev/null
+package jalview.ext.rbvi.chimera;
+
+import jalview.api.AlignViewportI;
+import jalview.api.AlignmentViewPanel;
+import jalview.api.FeatureRenderer;
+import jalview.api.SequenceRenderer;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.HiddenColumns;
+import jalview.datamodel.SequenceI;
+import jalview.renderer.seqfeatures.FeatureColourFinder;
+import jalview.structure.StructureMapping;
+import jalview.structures.models.AAStructureBindingModel;
+import jalview.util.Comparison;
+import jalview.util.IntRangeComparator;
+
+import java.awt.Color;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A class with common methods for building commands for Jmol, Chimera, or other
+ *
+ * @author gmcarstairs
+ */
+public abstract class StructureCommands
+{
+
+ /**
+ * Helper method to add one contiguous range to the AtomSpec model for the given
+ * value (creating the model if necessary). As used by Jalview, {@code value} is
+ * <ul>
+ * <li>a colour, when building a 'colour structure by sequence' command</li>
+ * <li>a feature value, when building a 'set Chimera attributes from features'
+ * command</li>
+ * </ul>
+ *
+ * @param map
+ * @param value
+ * @param model
+ * @param startPos
+ * @param endPos
+ * @param chain
+ */
+ protected static void addAtomSpecRange(Map<Object, AtomSpecModel> map,
+ Object value,
+ int model, int startPos, int endPos, String chain)
+ {
+ /*
+ * Get/initialize map of data for the colour
+ */
+ AtomSpecModel atomSpec = map.get(value);
+ if (atomSpec == null)
+ {
+ atomSpec = new AtomSpecModel();
+ map.put(value, atomSpec);
+ }
+
+ atomSpec.addRange(model, startPos, endPos, chain);
+ }
+
+ /**
+ * Build a data structure which records contiguous subsequences by model and
+ * chain. From this we can easily generate the Chimera or Jmol specific
+ * selection expression.
+ *
+ * <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 static Map<Object, AtomSpecModel> buildColoursMap(
+ AAStructureBindingModel binding, 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 = binding.getSequenceRenderer(viewPanel);
+ String[] files = binding.getStructureFiles();
+ SequenceI[][] sequence = binding.getSequence();
+
+ Map<Object, AtomSpecModel> colourMap = new LinkedHashMap<>();
+ Color lastColour = null;
+
+ for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
+ {
+ StructureMapping[] mapping = binding.getSsm()
+ .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 (binding.isHideHiddenRegions())
+ {
+ 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)
+ {
+ StructureCommands.addAtomSpecRange(colourMap, lastColour,
+ pdbfnum, startPos,
+ lastPos, lastChain);
+ }
+ startPos = pos;
+ }
+ lastColour = colour;
+ lastPos = pos;
+ lastChain = chain;
+ }
+ // final colour range
+ if (lastColour != null)
+ {
+ StructureCommands.addAtomSpecRange(colourMap, lastColour,
+ pdbfnum,
+ startPos, lastPos, lastChain);
+ }
+ }
+ }
+ }
+ }
+ return colourMap;
+ }
+
+ /**
+ * A helper method that takes a list of [start-end] ranges, format them as
+ * s1-e1,s2-e2 etc and appends to the string buffer. Ranges are sorted, and
+ * coalesced if they overlap. The chain token, if not null, is appended to each
+ * resulting subrange.
+ *
+ * @param sb
+ * @param rangeList
+ * @param chainToken
+ * @param firstPositionForModel
+ */
+ protected static void appendResidueRange(StringBuilder sb, List<int[]> rangeList,
+ String chainToken, boolean firstPositionForModel)
+ {
+ /*
+ * sort ranges into ascending start position order
+ */
+ Collections.sort(rangeList, IntRangeComparator.ASCENDING);
+
+ int start = rangeList.isEmpty() ? 0 : rangeList.get(0)[0];
+ int end = rangeList.isEmpty() ? 0 : rangeList.get(0)[1];
+
+ Iterator<int[]> iterator = rangeList.iterator();
+ while (iterator.hasNext())
+ {
+ int[] range = iterator.next();
+ if (range[0] <= end + 1)
+ {
+ /*
+ * range overlaps or is contiguous with the last one
+ * - so just extend the end position, and carry on
+ * (unless this is the last in the list)
+ */
+ end = Math.max(end, range[1]);
+ }
+ else
+ {
+ /*
+ * we have a break so append the last range
+ */
+ appendRange(sb, start, end, chainToken, firstPositionForModel);
+ firstPositionForModel = false;
+ start = range[0];
+ end = range[1];
+ }
+ }
+
+ /*
+ * and append the last range
+ */
+ if (!rangeList.isEmpty())
+ {
+ appendRange(sb, start, end, chainToken, firstPositionForModel);
+ }
+ }
+
+ /**
+ * A helper method that appends one start-end range, and an (optional) chain
+ * token to an atomspec (a null token is not appended)
+ *
+ * @param sb
+ * @param start
+ * @param end
+ * @param chainToken
+ * @param firstPositionForModel
+ */
+ protected static void appendRange(StringBuilder sb, int start, int end,
+ String chainToken, boolean firstPositionForModel)
+ {
+ if (!firstPositionForModel)
+ {
+ sb.append(",");
+ }
+ if (end == start)
+ {
+ sb.append(start);
+ }
+ else
+ {
+ sb.append(start).append("-").append(end);
+ }
+ if (chainToken != null)
+ {
+ sb.append(chainToken);
+ }
+ }
+
+}
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 java.util.BitSet;
import java.util.Collections;
import java.util.Iterator;
-import java.util.LinkedHashMap;
import java.util.List;
-import java.util.Map;
/**
*
}
/**
- * 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.
*
import jalview.datamodel.ColumnSelection;
import jalview.datamodel.Sequence;
import jalview.datamodel.SequenceI;
+import jalview.ext.rbvi.chimera.AtomSpecModel;
import jalview.gui.AlignFrame;
import jalview.gui.JvOptionPane;
import jalview.gui.SequenceRenderer;
// need some mappings!
StructureMappingcommandSet[] commands = JmolCommands
- .getColourBySequenceCommand(ssm, files, seqs, sr, af.alignPanel);
+ .getColourBySequenceCommand(ssm, files, seqs, sr,
+ af.alignPanel);
}
@Test(groups = { "Functional" })
SequenceI[][] seqs = new SequenceI[][] { { seq1 }, { seq2 } };
String[] files = new String[] { "seq1.pdb", "seq2.pdb" };
StructureSelectionManager ssm = new StructureSelectionManager();
-
+
/*
* map residues 1-10 to residues 21-30 (atoms 105-150) in structures
*/
- HashMap<Integer, int[]> map = new HashMap<Integer, int[]>();
+ HashMap<Integer, int[]> map = new HashMap<>();
for (int pos = 1; pos <= seq1.getLength(); pos++)
{
map.put(pos, new int[] { 20 + pos, 5 * (20 + pos) });
StructureMapping sm2 = new StructureMapping(seq2, "seq2.pdb", "pdb2",
"B", map, null);
ssm.addStructureMapping(sm2);
-
+
StructureMappingcommandSet[] commands = JmolCommands
- .getColourBySequenceCommand(ssm, files, seqs, sr, af.alignPanel);
+ .getColourBySequenceCommand(ssm, files, seqs, sr,
+ af.alignPanel);
assertEquals(commands.length, 2);
assertEquals(commands[0].commands.length, 1);
String chainACommand = commands[0].commands[0];
// M colour is #82827d == (130, 130, 125) (see strand.html help page)
- assertTrue(chainACommand
- .contains("select 21:A/1.1;color[130,130,125]")); // first one
+ assertTrue(
+ chainACommand.contains("select 21:A/1.1;color[130,130,125]")); // first one
// H colour is #60609f == (96, 96, 159)
assertTrue(chainACommand.contains(";select 22:A/1.1;color[96,96,159]"));
// hidden columns are Gray (128, 128, 128)
assertTrue(chainACommand
.contains(";select 23-25:A/1.1;color[128,128,128]"));
// S and G are both coloured #4949b6 == (73, 73, 182)
- assertTrue(chainACommand
- .contains(";select 26-30:A/1.1;color[73,73,182]"));
+ assertTrue(
+ chainACommand.contains(";select 26-30:A/1.1;color[73,73,182]"));
String chainBCommand = commands[1].commands[0];
// M colour is #82827d == (130, 130, 125)
- assertTrue(chainBCommand
- .contains("select 21:B/2.1;color[130,130,125]"));
+ assertTrue(
+ chainBCommand.contains("select 21:B/2.1;color[130,130,125]"));
// V colour is #ffff00 == (255, 255, 0)
- assertTrue(chainBCommand
-.contains(";select 22:B/2.1;color[255,255,0]"));
+ assertTrue(chainBCommand.contains(";select 22:B/2.1;color[255,255,0]"));
// hidden columns are Gray (128, 128, 128)
assertTrue(chainBCommand
.contains(";select 23-25:B/2.1;color[128,128,128]"));
// S and G are both coloured #4949b6 == (73, 73, 182)
- assertTrue(chainBCommand
- .contains(";select 26-30:B/2.1;color[73,73,182]"));
+ assertTrue(
+ chainBCommand.contains(";select 26-30:B/2.1;color[73,73,182]"));
+ }
+
+ @Test(groups = { "Functional" })
+ public void testGetAtomSpec()
+ {
+ AtomSpecModel model = new AtomSpecModel();
+ assertEquals(JmolCommands.getAtomSpec(model), "");
+
+ /*
+ * Jalview numbers models from 0, Jmol from 1
+ */
+ model.addRange(1, 2, 4, "A");
+ assertEquals(JmolCommands.getAtomSpec(model), "2-4:A/2.1");
+
+ model.addRange(1, 8, 8, "A");
+ assertEquals(JmolCommands.getAtomSpec(model), "(2-4,8)&:A/2.1");
+
+ model.addRange(1, 5, 7, "B");
+ assertEquals(JmolCommands.getAtomSpec(model),
+ "(2-4,8)&:A/2.1,5-7:B/2.1");
+
+ model.addRange(1, 3, 5, "A");
+ // 3-5 merges with 2-4 to make 2-5:
+ assertEquals(JmolCommands.getAtomSpec(model),
+ "(2-5,8)&:A/2.1,5-7:B/2.1");
+
+ model.addRange(0, 1, 4, "B");
+ assertEquals(JmolCommands.getAtomSpec(model),
+ "1-4:B/1.1,(2-5,8)&:A/2.1,5-7:B/2.1");
+
+ model.addRange(0, 5, 9, "C");
+ assertEquals(JmolCommands.getAtomSpec(model),
+ "1-4:B/1.1,5-9:C/1.1,(2-5,8)&:A/2.1,5-7:B/2.1");
+
+ model.addRange(1, 8, 10, "B");
+ // 8-10 extends 5-7 to make 5-10
+ // note code generates (5-10)&:B which is equivalent to 5-10:B
+ assertEquals(JmolCommands.getAtomSpec(model),
+ "1-4:B/1.1,5-9:C/1.1,(2-5,8)&:A/2.1,(5-10)&:B/2.1");
+
+ model.addRange(1, 8, 9, "B");
+ // subsumed by 5-10 so makes no difference
+ assertEquals(JmolCommands.getAtomSpec(model),
+ "1-4:B/1.1,5-9:C/1.1,(2-5,8)&:A/2.1,(5-10)&:B/2.1");
+
+ model.addRange(0, 3, 10, "C");
+ // subsumes 5-9 so replaces it
+ assertEquals(JmolCommands.getAtomSpec(model),
+ "1-4:B/1.1,(3-10)&:C/1.1,(2-5,8)&:A/2.1,(5-10)&:B/2.1");
+
+ // empty chain code - e.g. from homology modelling
+ model.addRange(5, 25, 35, " ");
+ assertEquals(JmolCommands.getAtomSpec(model),
+ "1-4:B/1.1,(3-10)&:C/1.1,(2-5,8)&:A/2.1,(5-10)&:B/2.1,25-35:/6.1");
}
}
PA.setValue(mockBinding, "ssm", ssm);
PA.setValue(mockBinding, "sequence", seqs);
- Map<Object, AtomSpecModel> colourMap = mockBinding
- .buildColoursMap(af.alignPanel);
+ Map<Object, AtomSpecModel> colourMap = StructureCommands.buildColoursMap(mockBinding, af.alignPanel);
String[] commands = ChimeraCommands
.getColourBySequenceCommand(colourMap, mockBinding);
assertEquals(1, commands.length);
{
AtomSpecModel model = new AtomSpecModel();
assertEquals(ChimeraCommands.getAtomSpec(model, mockBinding), "");
+
model.addRange(1, 2, 4, "A");
assertEquals(ChimeraCommands.getAtomSpec(model, mockBinding),
"#1:2-4.A");
+
model.addRange(1, 8, 8, "A");
assertEquals(ChimeraCommands.getAtomSpec(model, mockBinding),
"#1:2-4.A,8.A");
+
model.addRange(1, 5, 7, "B");
assertEquals(ChimeraCommands.getAtomSpec(model, mockBinding),
"#1:2-4.A,8.A,5-7.B");
+
model.addRange(1, 3, 5, "A");
+ // 3-5 combines with 2-4 to make 2-5:
assertEquals(ChimeraCommands.getAtomSpec(model, mockBinding),
"#1:2-5.A,8.A,5-7.B");
+
model.addRange(0, 1, 4, "B");
assertEquals(ChimeraCommands.getAtomSpec(model, mockBinding),
"#0:1-4.B|#1:2-5.A,8.A,5-7.B");
+
model.addRange(0, 5, 9, "C");
assertEquals(ChimeraCommands.getAtomSpec(model, mockBinding),
"#0:1-4.B,5-9.C|#1:2-5.A,8.A,5-7.B");
+
model.addRange(1, 8, 10, "B");
+ // 8-10 extends 5-7 to make 5-10
assertEquals(ChimeraCommands.getAtomSpec(model, mockBinding),
"#0:1-4.B,5-9.C|#1:2-5.A,8.A,5-10.B");
+
model.addRange(1, 8, 9, "B");
+ // subsumed range makes no difference
assertEquals(ChimeraCommands.getAtomSpec(model, mockBinding),
"#0:1-4.B,5-9.C|#1:2-5.A,8.A,5-10.B");
- model.addRange(0, 3, 10, "C"); // subsumes 5-9
+
+ model.addRange(0, 3, 10, "C");
+ // subsumes 5-9 so replaces it
assertEquals(ChimeraCommands.getAtomSpec(model, mockBinding),
"#0:1-4.B,3-10.C|#1:2-5.A,8.A,5-10.B");
- model.addRange(5, 25, 35, " "); // empty chain code - e.g. from homology
- // modelling
+
+ // empty chain code - e.g. from homology modelling
+ model.addRange(5, 25, 35, " ");
assertEquals(ChimeraCommands.getAtomSpec(model, mockBinding),
"#0:1-4.B,3-10.C|#1:2-5.A,8.A,5-10.B|#5:25-35.");