*/
package jalview.ext.rbvi.chimera;
-import jalview.util.IntRangeComparator;
-
import java.util.ArrayList;
import java.util.Collections;
-import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
/**
- * A class to model a Chimera atomspec pattern, for example
- *
- * <pre>
- * #0:15.A,28.A,54.A,63.A,70-72.A,83-84.A,97-98.A|#1:2.A,6.A,11.A,13-14.A,70.A,82.A,96-97.A
- * </pre>
- *
- * where
- * <ul>
- * <li>#0 is a model number</li>
- * <li>15 or 70-72 is a residue number, or range of residue numbers</li>
- * <li>.A is a chain identifier</li>
- * <li>residue ranges are separated by comma</li>
- * <li>atomspecs for distinct models are separated by | (or)</li>
- * </ul>
- *
- * <pre>
- * @see http://www.cgl.ucsf.edu/chimera/current/docs/UsersGuide/midas/frameatom_spec.html
- * </pre>
+ * A class to model a Chimera or Jmol residue set, as
+ * {@code Map<modelNumber, Map<chainId, List<residueRange>>>}. This can then be
+ * traversed to generate the required display command in Chimera or Jmol syntax.
*/
public class AtomSpecModel
{
*/
public AtomSpecModel()
{
- atomSpec = new TreeMap<Integer, Map<String, List<int[]>>>();
+ atomSpec = new TreeMap<>();
+ }
+
+ public Map<Integer, Map<String, List<int[]>>> getMap()
+ {
+ return atomSpec;
}
/**
Map<String, List<int[]>> modelData = atomSpec.get(model);
if (modelData == null)
{
- atomSpec.put(model, modelData = new TreeMap<String, List<int[]>>());
+ atomSpec.put(model, modelData = new TreeMap<>());
}
/*
List<int[]> chainData = modelData.get(chain);
if (chainData == null)
{
- chainData = new ArrayList<int[]>();
+ chainData = new ArrayList<>();
modelData.put(chain, chainData);
}
}
/**
- * Returns the range(s) formatted as a Chimera atomspec
+ * Answers an iterable set of the structure models in this model
*
* @return
*/
- public String getAtomSpec()
+ public Iterable<Integer> getModels()
{
- StringBuilder sb = new StringBuilder(128);
- boolean firstModel = true;
- for (Integer model : atomSpec.keySet())
- {
- if (!firstModel)
- {
- sb.append("|");
- }
- firstModel = false;
- sb.append("#").append(model).append(":");
-
- boolean firstPositionForModel = true;
- final Map<String, List<int[]>> modelData = atomSpec.get(model);
-
- for (String chain : modelData.keySet())
- {
- chain = chain.trim();
-
- List<int[]> rangeList = modelData.get(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;
- }
- }
- }
- return sb.toString();
+ return atomSpec.keySet();
}
/**
- * @param sb
- * @param start
- * @param end
- * @param chain
- * @param firstPositionForModel
+ * Answers an iterable set of the chains in this model for the given structure
+ * model, or an empty set if none
+ *
+ * @param model
+ * @return
*/
- protected void appendRange(StringBuilder sb, int start, int end,
- String chain, boolean firstPositionForModel)
+ public Iterable<String> getChains(Integer model)
{
- if (!firstPositionForModel)
- {
- sb.append(",");
- }
- if (end == start)
+ if (atomSpec.containsKey(model))
{
- sb.append(start);
+ return atomSpec.get(model).keySet();
}
- else
- {
- sb.append(start).append("-").append(end);
- }
- if (chain.length() > 0)
+ return Collections.emptySet();
+ }
+
+ public List<int[]> getRanges(Integer model, String chain)
+ {
+ Map<String, List<int[]>> modelData = atomSpec.get(model);
+ if (modelData != null)
{
- sb.append(".").append(chain);
+ List<int[]> chainData = modelData.get(chain);
+ if (chainData != null)
+ {
+ return chainData;
+ }
}
+ return Collections.EMPTY_LIST;
}
}