+ List<StructureCommandI> commands = new ArrayList<>();
+ for (String featureType : featureMap.keySet())
+ {
+ String attributeName = makeAttributeName(featureType);
+
+ /*
+ * clear down existing attributes for this feature
+ */
+ // 'problem' - sets attribute to None on all residues - overkill?
+ // commands.add("~setattr r " + attributeName + " :*");
+
+ Map<Object, AtomSpecModel> values = featureMap.get(featureType);
+ for (Object value : values.keySet())
+ {
+ /*
+ * for each distinct value recorded for this feature type,
+ * add a command to set the attribute on the mapped residues
+ * Put values in single quotes, encoding any embedded single quotes
+ */
+ AtomSpecModel atomSpecModel = values.get(value);
+ String featureValue = value.toString();
+ featureValue = featureValue.replaceAll("\\'", "'");
+ StructureCommandI cmd = setAttribute(attributeName, featureValue,
+ atomSpecModel);
+ commands.add(cmd);
+ }
+ }
+
+ return commands;
+ }
+
+ /**
+ * Returns a viewer command to set the given residue attribute value on
+ * residues specified by the AtomSpecModel, for example
+ *
+ * <pre>
+ * setatr res jv_chain 'primary' #1:12-34,48-55.B
+ * </pre>
+ *
+ * @param attributeName
+ * @param attributeValue
+ * @param atomSpecModel
+ * @return
+ */
+ protected StructureCommandI setAttribute(String attributeName,
+ String attributeValue,
+ AtomSpecModel atomSpecModel)
+ {
+ StringBuilder sb = new StringBuilder(128);
+ sb.append("setattr res ").append(attributeName).append(" '")
+ .append(attributeValue).append("' ");
+ sb.append(getAtomSpec(atomSpecModel, false));
+ return new StructureCommand(sb.toString());
+ }
+
+ /**
+ * Makes a prefixed and valid Chimera attribute name. A jv_ prefix is applied
+ * for a 'Jalview' namespace, and any non-alphanumeric character is converted
+ * to an underscore.
+ *
+ * @param featureType
+ * @return
+ * @see https://www.cgl.ucsf.edu/chimera/current/docs/UsersGuide/midas/setattr.html
+ */
+ @Override
+ protected String makeAttributeName(String featureType)
+ {
+ String attName = super.makeAttributeName(featureType);
+
+ /*
+ * Chimera treats an attribute name ending in 'color' as colour-valued;
+ * Jalview doesn't, so prevent this by appending an underscore
+ */
+ if (attName.toUpperCase(Locale.ROOT).endsWith("COLOR"))
+ {
+ attName += "_";
+ }
+
+ return attName;
+ }
+
+ @Override
+ public StructureCommandI colourByChain()
+ {
+ return COLOUR_BY_CHAIN;
+ }
+
+ @Override
+ public List<StructureCommandI> colourByCharge()
+ {
+ return Arrays.asList(COLOUR_BY_CHARGE);
+ }
+
+ @Override
+ public String getResidueSpec(String residue)
+ {
+ return "::" + residue;
+ }
+
+ @Override
+ public StructureCommandI setBackgroundColour(Color col)
+ {
+ // https://www.cgl.ucsf.edu/chimera/current/docs/UsersGuide/midas/set.html#bgcolor
+ return new StructureCommand("set bgColor " + ColorUtils.toTkCode(col));
+ }
+
+ @Override
+ public StructureCommandI focusView()
+ {
+ return FOCUS_VIEW;
+ }