package jalview.structure; import java.awt.Color; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Map.Entry; /** * A base class holding methods useful to all classes that implement commands * for structure viewers * * @author gmcarstairs * */ public abstract class StructureCommandsBase implements StructureCommandsI { public static final String NAMESPACE_PREFIX = "jv_"; private static final String CMD_SEPARATOR = ";"; /** * Returns something that separates concatenated commands * * @return */ protected String getCommandSeparator() { return CMD_SEPARATOR; } /** * Returns the lowest model number used by the structure viewer * * @return */ @Override public int getModelStartNo() { return 0; } /** * 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 * * * @param map * @param value * @param model * @param startPos * @param endPos * @param chain */ public static final void addAtomSpecRange(Map map, Object value, String 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); } /** * Makes a structure viewer attribute name for a Jalview feature type by * prefixing it with "jv_", and replacing any non-alphanumeric characters with * an underscore * * @param featureType * @return */ protected String makeAttributeName(String featureType) { StringBuilder sb = new StringBuilder(); if (featureType != null) { for (char c : featureType.toCharArray()) { sb.append(Character.isLetterOrDigit(c) ? c : '_'); } } String attName = NAMESPACE_PREFIX + sb.toString(); return attName; } /** * Traverse the map of colours/models/chains/positions to construct a list of * 'color' commands (one per distinct colour used). The format of each command * is specific to the structure viewer. *

* The default implementation returns a single command containing one command * per colour, concatenated. * * @param colourMap * @return */ @Override public List colourBySequence( Map colourMap) { List commands = new ArrayList<>(); StringBuilder sb = new StringBuilder(colourMap.size() * 20); boolean first = true; for (Object key : colourMap.keySet()) { Color colour = (Color) key; final AtomSpecModel colourData = colourMap.get(colour); StructureCommandI command = getColourCommand(colourData, colour); if (!first) { sb.append(getCommandSeparator()); } first = false; sb.append(command.getCommand()); } commands.add(new StructureCommand(sb.toString())); return commands; } /** * Returns a command to colour the atoms represented by {@code atomSpecModel} * with the colour specified by {@code colourCode}. * * @param atomSpecModel * @param colour * @return */ protected StructureCommandI getColourCommand(AtomSpecModel atomSpecModel, Color colour) { String atomSpec = getAtomSpec(atomSpecModel, AtomSpecType.RESIDUE_ONLY); return colourResidues(atomSpec, colour); } /** * Returns a command to colour the atoms described (in viewer command syntax) * by {@code atomSpec} with the colour specified by {@code colourCode} * * @param atomSpec * @param colour * @return */ protected abstract StructureCommandI colourResidues(String atomSpec, Color colour); @Override public List colourByResidues( Map colours) { List commands = new ArrayList<>(); for (Entry entry : colours.entrySet()) { commands.add(colourResidue(entry.getKey(), entry.getValue())); } return commands; } private StructureCommandI colourResidue(String resName, Color col) { String atomSpec = getResidueSpec(resName); return colourResidues(atomSpec, col); } /** * Helper method to append one start-end range to an atomspec string * * @param sb * @param start * @param end * @param chain * @param firstPositionForModel */ protected void appendRange(StringBuilder sb, int start, int end, String chain, boolean firstPositionForModel, boolean isChimeraX) { if (!firstPositionForModel) { sb.append(","); } if (end == start) { sb.append(start); } else { sb.append(start).append("-").append(end); } if (!isChimeraX) { sb.append("."); if (!" ".equals(chain)) { sb.append(chain); } } } /** * Returns the atom specifier meaning all occurrences of the given residue * * @param residue * @return */ protected abstract String getResidueSpec(String residue); @Override public List setAttributes( Map> featureValues) { // default does nothing, override where this is implemented return null; } @Override public List startNotifications(String uri) { return null; } @Override public List stopNotifications() { return null; } @Override public StructureCommandI getSelectedResidues() { return null; } @Override public StructureCommandI listResidueAttributes() { return null; } @Override public StructureCommandI getResidueAttributes(String attName) { return null; } }