label.right_click_to_edit_currently_selected_parameter = Right click to edit currently selected parameter.
label.let_jmol_manage_structure_colours = Let Jmol manage structure colours
label.let_chimera_manage_structure_colours = Let Chimera manage structure colours
++label.fetch_chimera_attributes = Fetch Chimera attributes
++label.fetch_chimera_attributes_tip = Copy Chimera attribute to Jalview feature
label.marks_leaves_tree_not_associated_with_sequence = Marks leaves of tree not associated with a sequence
label.index_web_services_menu_by_host_site = Index web services in menu by the host site
label.option_want_informed_web_service_URL_cannot_be_accessed_jalview_when_starts_up = Check this option if you want to be informed<br>when a web service URL cannot be accessed by Jalview<br>when it starts up
label.SEQUENCE_ID_for_DB_ACCESSION1 = Please review your URL links in the 'Connections' tab of the Preferences window:
label.SEQUENCE_ID_for_DB_ACCESSION2 = URL links using '$SEQUENCE_ID$' for DB accessions now use '$DB_ACCESSION$'.
label.do_not_display_again = Do not display this message again
+exception.url_cannot_have_miriam_id = {0} is a MIRIAM id and cannot be used as a custom url name
+exception.url_cannot_have_duplicate_id = {0} cannot be used as a label for more than one line
+label.filter = Filter text:
+action.customfilter = Custom only
+action.showall = Show All
+label.insert = Insert:
+action.seq_id = $SEQUENCE_ID$
+action.db_acc = $DB_ACCESSION$
+label.primary = Double Click
+label.inmenu = In Menu
+label.id = ID
+label.database = Database
+label.urltooltip = Only one url, which must use a sequence id, can be selected for the 'On Click' option
+label.edit_sequence_url_link = Edit sequence URL link
+warn.name_cannot_be_duplicate = User-defined URL names must be unique and cannot be MIRIAM ids
+label.invalid_name = Invalid Name !
label.output_seq_details = Output Sequence Details to list all database references
- label.urllinks = Links
++label.urllinks = Links
public class ChimeraCommands
{
+ public static final String NAMESPACE_PREFIX = "jv_";
+
/**
- * utility to construct the commands to colour chains by the given alignment
- * for passing to Chimera
- *
- * @returns Object[] { Object[] { <model being coloured>,
+ * Constructs Chimera commands to colour residues as per the Jalview alignment
*
+ * @param ssm
+ * @param files
+ * @param sequence
+ * @param sr
+ * @param fr
+ * @param alignment
+ * @return
*/
- public static StructureMappingcommandSet getColourBySequenceCommand(
+ public static StructureMappingcommandSet[] getColourBySequenceCommand(
StructureSelectionManager ssm, String[] files,
SequenceI[][] sequence, SequenceRenderer sr, FeatureRenderer fr,
AlignmentI alignment)
{
- Map<Color, SortedMap<Integer, Map<String, List<int[]>>>> colourMap = buildColoursMap(
- ssm, files, sequence, sr, fr, alignment);
- Map<Object, AtomSpecModel> colourMap = buildColoursMap(
- ssm, files, sequence, sr, fr, alignment);
++ Map<Object, AtomSpecModel> colourMap = buildColoursMap(ssm, files,
++ sequence, sr, fr, alignment);
List<String> colourCommands = buildColourCommands(colourMap);
StructureMappingcommandSet cs = new StructureMappingcommandSet(
ChimeraCommands.class, null,
- colourCommands.toArray(new String[0]));
+ colourCommands.toArray(new String[colourCommands.size()]));
- return cs;
+ return new StructureMappingcommandSet[] { cs };
}
/**
}
sb.append("color ").append(colourCode).append(" ");
firstColour = false;
- boolean firstModelForColour = true;
- final Map<Integer, Map<String, List<int[]>>> colourData = colourMap
- .get(colour);
- for (Integer model : colourData.keySet())
- final AtomSpecModel colourData = colourMap
- .get(colour);
++ final AtomSpecModel colourData = colourMap.get(colour);
+ sb.append(colourData.getAtomSpec());
+ }
+ commands.add(sb.toString());
+ return commands;
+ }
+
+ /**
+ * Traverses a map of { modelNumber, {chain, {list of from-to ranges} } } and
+ * builds a Chimera format atom spec
+ *
+ * @param modelAndChainRanges
+ */
+ protected static String getAtomSpec(
+ Map<Integer, Map<String, List<int[]>>> modelAndChainRanges)
+ {
+ StringBuilder sb = new StringBuilder(128);
+ boolean firstModelForColour = true;
+ for (Integer model : modelAndChainRanges.keySet())
+ {
+ boolean firstPositionForModel = true;
+ if (!firstModelForColour)
{
- boolean firstPositionForModel = true;
- if (!firstModelForColour)
- {
- sb.append("|");
- }
- firstModelForColour = false;
- sb.append("#").append(model).append(":");
+ sb.append("|");
+ }
+ firstModelForColour = false;
+ sb.append("#").append(model).append(":");
- final Map<String, List<int[]>> modelData = colourData.get(model);
- for (String chain : modelData.keySet())
+ final Map<String, List<int[]>> modelData = modelAndChainRanges
+ .get(model);
+ for (String chain : modelData.keySet())
+ {
+ boolean hasChain = !"".equals(chain.trim());
+ for (int[] range : modelData.get(chain))
{
- boolean hasChain = !"".equals(chain.trim());
- for (int[] range : modelData.get(chain))
+ if (!firstPositionForModel)
{
- if (!firstPositionForModel)
- {
- sb.append(",");
- }
- if (range[0] == range[1])
- {
- sb.append(range[0]);
- }
- else
- {
- sb.append(range[0]).append("-").append(range[1]);
- }
- if (hasChain)
- {
- sb.append(".").append(chain);
- }
- firstPositionForModel = false;
+ sb.append(",");
+ }
+ if (range[0] == range[1])
+ {
+ sb.append(range[0]);
+ }
+ else
+ {
+ sb.append(range[0]).append("-").append(range[1]);
+ }
+ if (hasChain)
+ {
+ sb.append(".").append(chain);
}
+ firstPositionForModel = false;
}
}
}
// final colour range
if (lastColour != null)
{
- addColourRange(colourMap, lastColour, pdbfnum, startPos,
- lastPos, lastChain);
- addRange(colourMap, lastColour, pdbfnum, startPos,
- lastPos, lastChain);
++ addColourRange(colourMap, lastColour, pdbfnum, startPos, lastPos,
++ lastChain);
}
// break;
}
* @param endPos
* @param chain
*/
- protected static void addColourRange(
- Map<Color, SortedMap<Integer, Map<String, List<int[]>>>> colourMap,
- Color colour, int model, int startPos, int endPos, String chain)
- protected static void addRange(Map<Object, AtomSpecModel> map,
++ protected static void addColourRange(Map<Object, AtomSpecModel> map,
+ Object key, int model, int startPos, int endPos, String chain)
{
/*
* Get/initialize map of data for the colour
*/
- SortedMap<Integer, Map<String, List<int[]>>> colourData = colourMap
- .get(colour);
- if (colourData == null)
+ AtomSpecModel atomSpec = map.get(key);
+ if (atomSpec == null)
{
- colourMap
- .put(colour,
- colourData = new TreeMap<Integer, Map<String, List<int[]>>>());
+ atomSpec = new AtomSpecModel();
+ map.put(key, atomSpec);
}
- /*
- * Get/initialize map of data for the colour and model
- */
- Map<String, List<int[]>> modelData = colourData.get(model);
- if (modelData == null)
+ 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.
+ *
+ * @param ssm
+ * @param files
+ * @param seqs
+ * @param fr
+ * @param alignment
+ * @return
+ */
+ public static StructureMappingcommandSet getSetAttributeCommandsForFeatures(
+ StructureSelectionManager ssm, String[] files,
+ SequenceI[][] seqs, FeatureRenderer fr, AlignmentI alignment)
+ {
+ Map<String, Map<Object, AtomSpecModel>> featureMap = buildFeaturesMap(
+ ssm, files, seqs, fr, alignment);
+
+ List<String> commands = buildSetAttributeCommands(featureMap);
+
+ StructureMappingcommandSet cs = new StructureMappingcommandSet(
+ ChimeraCommands.class, null,
+ commands.toArray(new String[commands.size()]));
+
+ return cs;
+ }
+
+ /**
+ * <pre>
+ * Helper method to build a map of
+ * { featureType, { feature value, AtomSpecModel } }
+ * </pre>
+ *
+ * @param ssm
+ * @param files
+ * @param seqs
+ * @param fr
+ * @param alignment
+ * @return
+ */
+ protected static Map<String, Map<Object, AtomSpecModel>> buildFeaturesMap(
+ StructureSelectionManager ssm, String[] files,
+ SequenceI[][] seqs, FeatureRenderer fr, AlignmentI alignment)
+ {
+ Map<String, Map<Object, AtomSpecModel>> theMap = new LinkedHashMap<String, Map<Object, AtomSpecModel>>();
+
+ List<String> visibleFeatures = fr.getDisplayedFeatureTypes();
+ if (visibleFeatures.isEmpty())
{
- colourData.put(model, modelData = new TreeMap<String, List<int[]>>());
+ return theMap;
}
-
+
- /*
- * Get/initialize map of data for colour, model and chain
- */
- List<int[]> chainData = modelData.get(chain);
- if (chainData == null)
+ for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
+ {
+ StructureMapping[] mapping = ssm.getMapping(files[pdbfnum]);
+
+ if (mapping == null || mapping.length < 1)
+ {
+ continue;
+ }
+
+ for (int seqNo = 0; seqNo < seqs[pdbfnum].length; seqNo++)
+ {
+ for (int m = 0; m < mapping.length; m++)
+ {
+ final SequenceI seq = seqs[pdbfnum][seqNo];
+ int sp = alignment.findIndex(seq);
+ if (mapping[m].getSequence() == seq && sp > -1)
+ {
+ /*
+ * found a sequence with a mapping to a structure;
+ * now scan its features
+ */
+ SequenceI asp = alignment.getSequenceAt(sp);
+
+ 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, Map<Object, AtomSpecModel>> theMap, int modelNumber)
+ {
+ SequenceFeature[] sfs = seq.getSequenceFeatures();
+ if (sfs == null)
+ {
+ return;
+ }
+
+ for (SequenceFeature sf : sfs)
+ {
+ String type = sf.getType();
+
+ /*
+ * Only copy visible features, don't copy any which originated
+ * from Chimera, and suppress uninteresting ones (e.g. RESNUM)
+ */
+ boolean isFromViewer = JalviewChimeraBinding.CHIMERA_FEATURE_GROUP
+ .equals(sf.getFeatureGroup());
+ if (isFromViewer || !visibleFeatures.contains(type))
+ {
+ continue;
+ }
+ List<int[]> mappedRanges = mapping.getPDBResNumRanges(sf.getBegin(),
+ sf.getEnd());
+
+ if (!mappedRanges.isEmpty())
+ {
+ String value = sf.getDescription();
+ if (value == null || value.length() == 0)
+ {
+ value = type;
+ }
+ float score = sf.getScore();
+ if (score != 0f && !Float.isNaN(score))
+ {
+ value = Float.toString(score);
+ }
+ Map<Object, AtomSpecModel> featureValues = theMap.get(type);
+ if (featureValues == null)
+ {
+ featureValues = new HashMap<Object, AtomSpecModel>();
+ theMap.put(type, featureValues);
+ }
+ for (int[] range : mappedRanges)
+ {
- addRange(featureValues, value, modelNumber, range[0], range[1],
++ addColourRange(featureValues, value, modelNumber, range[0], range[1],
+ mapping.getChain());
+ }
+ }
+ }
+ }
+
+ /**
+ * Traverse the map of features/values/models/chains/positions to construct a
+ * list of 'setattr' commands (one per distinct feature type and value).
+ * <p>
+ * The format of each command is
+ *
+ * <pre>
+ * <blockquote> setattr r <featureName> " " #modelnumber:range.chain
+ * e.g. setattr r jv:chain <value> #0:2.B,4.B,9-12.B|#1:1.A,2-6.A,...
+ * </blockquote>
+ * </pre>
+ *
+ * @param featureMap
+ * @return
+ */
+ protected static List<String> buildSetAttributeCommands(
+ Map<String, Map<Object, AtomSpecModel>> featureMap)
+ {
+ List<String> commands = new ArrayList<String>();
+ for (String featureType : featureMap.keySet())
{
- modelData.put(chain, chainData = new ArrayList<int[]>());
+ 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
+ */
+ StringBuilder sb = new StringBuilder(128);
+ sb.append("setattr r ").append(attributeName).append(" \"")
+ .append(value.toString()).append("\" ");
+ sb.append(values.get(value).getAtomSpec());
+ commands.add(sb.toString());
+ }
}
+ return commands;
+ }
+
+ /**
+ * 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 <pre>
+ * @see https://www.cgl.ucsf.edu/chimera/current/docs/UsersGuide/midas/setattr.html
+ * </pre>
+ */
+ protected static 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();
+
/*
- * Add the start/end positions
+ * Chimera treats an attribute name ending in 'color' as colour-valued;
+ * Jalview doesn't, so prevent this by appending an underscore
*/
- chainData.add(new int[] { startPos, endPos });
+ if (attName.toUpperCase().endsWith("COLOR"))
+ {
+ attName += "_";
+ }
+
+ return attName;
}
}
*/
public abstract void refreshPdbEntries();
+ /**
+ * map between index of model filename returned from getPdbFile and the first
+ * index of models from this file in the viewer. Note - this is not trimmed -
+ * use getPdbFile to get number of unique models.
+ */
+ private int _modelFileNameMap[];
+
++
// ////////////////////////////////
// /StructureListener
@Override
package jalview.gui;
import jalview.bin.Cache;
-import jalview.datamodel.Alignment;
import jalview.datamodel.AlignmentI;
-import jalview.datamodel.ColumnSelection;
import jalview.datamodel.PDBEntry;
import jalview.datamodel.SequenceI;
+ import jalview.ext.rbvi.chimera.ChimeraCommands;
import jalview.ext.rbvi.chimera.JalviewChimeraBinding;
import jalview.gui.StructureViewer.ViewerType;
import jalview.io.DataSourceType;
import jalview.ws.dbsources.Pdb;
import java.awt.event.ActionEvent;
+ import java.awt.event.ActionListener;
-import java.awt.event.ItemEvent;
-import java.awt.event.ItemListener;
+ import java.awt.event.MouseAdapter;
+ import java.awt.event.MouseEvent;
-import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
-import java.io.PrintWriter;
import java.util.ArrayList;
+ import java.util.Collections;
import java.util.List;
import java.util.Random;
-import java.util.Vector;
import javax.swing.JCheckBoxMenuItem;
-import javax.swing.JColorChooser;
import javax.swing.JInternalFrame;
+ import javax.swing.JMenu;
+ import javax.swing.JMenuItem;
-import javax.swing.JOptionPane;
import javax.swing.event.InternalFrameAdapter;
import javax.swing.event.InternalFrameEvent;
-import javax.swing.event.MenuEvent;
-import javax.swing.event.MenuListener;
/**
* GUI elements for handling an external chimera display
{
private JalviewChimeraBinding jmb;
-- private boolean allChainsSelected = false;
--
private IProgressIndicator progressBar = null;
/*
.getString("label.colour_with_chimera"));
viewerColour.setToolTipText(MessageManager
.getString("label.let_chimera_manage_structure_colours"));
- helpItem.setText(MessageManager.getString("label.chimera_help"));
- seqColour.setSelected(jmb.isColourBySequence());
- viewerColour.setSelected(!jmb.isColourBySequence());
- if (_colourwith == null)
- {
- _colourwith = new Vector<AlignmentPanel>();
- }
- if (_alignwith == null)
- {
- _alignwith = new Vector<AlignmentPanel>();
- }
-
- // save As not yet implemented
- savemenu.setVisible(false);
- ViewSelectionMenu seqColourBy = new ViewSelectionMenu(
- MessageManager.getString("label.colour_by"), this, _colourwith,
- new ItemListener()
- {
- @Override
- public void itemStateChanged(ItemEvent e)
- {
- if (!seqColour.isSelected())
- {
- seqColour.doClick();
- }
- else
- {
- // update the Chimera display now.
- seqColour_actionPerformed(null);
- }
- }
- });
- viewMenu.add(seqColourBy);
+ helpItem.setText(MessageManager.getString("label.chimera_help"));
+ savemenu.setVisible(false); // not yet implemented
viewMenu.add(fitToWindow);
+
- final ItemListener handler;
- JMenu alpanels = new ViewSelectionMenu(
- MessageManager.getString("label.superpose_with"), this,
- _alignwith, handler = new ItemListener()
- {
- @Override
- public void itemStateChanged(ItemEvent e)
- {
- alignStructs.setEnabled(_alignwith.size() > 0);
- alignStructs.setToolTipText(MessageManager
- .formatMessage(
- "label.align_structures_using_linked_alignment_views",
- new Object[] { new Integer(_alignwith
- .size()).toString() }));
- }
- });
- handler.itemStateChanged(null);
- viewerActionMenu.add(alpanels);
- viewerActionMenu.addMenuListener(new MenuListener()
- {
-
- @Override
- public void menuSelected(MenuEvent e)
- {
- handler.itemStateChanged(null);
- }
-
- @Override
- public void menuDeselected(MenuEvent e)
- {
- // TODO Auto-generated method stub
- }
-
- @Override
- public void menuCanceled(MenuEvent e)
- {
- // TODO Auto-generated method stub
- }
- });
-
+ JMenuItem writeFeatures = new JMenuItem(
+ MessageManager.getString("label.create_chimera_attributes"));
+ writeFeatures.setToolTipText(MessageManager
+ .getString("label.create_chimera_attributes_tip"));
+ writeFeatures.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ sendFeaturesToChimera();
+ }
+ });
+ viewerActionMenu.add(writeFeatures);
+
- final JMenu fetchAttributes = new JMenu("Fetch Chimera attributes");
- fetchAttributes
- .setToolTipText("Copy Chimera attribute to Jalview feature");
++ final JMenu fetchAttributes = new JMenu(
++ MessageManager.getString("label.fetch_chimera_attributes"));
++ fetchAttributes.setToolTipText(MessageManager
++ .getString("label.fetch_chimera_attributes_tip"));
+ fetchAttributes.addMouseListener(new MouseAdapter()
+ {
+
+ @Override
+ public void mouseEntered(MouseEvent e)
+ {
+ buildAttributesMenu(fetchAttributes);
+ }
+ });
+ viewerActionMenu.add(fetchAttributes);
+
+ }
+
+ /**
+ * Query Chimera for its residue attribute names and add them as items off the
+ * attributes menu
+ *
+ * @param attributesMenu
+ */
+ protected void buildAttributesMenu(JMenu attributesMenu)
+ {
+ List<String> atts = jmb.sendChimeraCommand("list resattr", true);
+ if (atts == null)
+ {
+ return;
+ }
+ attributesMenu.removeAll();
+ Collections.sort(atts);
+ for (String att : atts)
+ {
+ final String attName = att.split(" ")[1];
+
+ /*
+ * ignore 'jv_*' attributes, as these are Jalview features that have
+ * been transferred to residue attributes in Chimera!
+ */
+ if (!attName.startsWith(ChimeraCommands.NAMESPACE_PREFIX))
+ {
+ JMenuItem menuItem = new JMenuItem(attName);
+ menuItem.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ getChimeraAttributes(attName);
+ }
+ });
+ attributesMenu.add(menuItem);
+ }
+ }
+ }
+
+ /**
+ * Read residues in Chimera with the given attribute name, and set as features
+ * on the corresponding sequence positions (if any)
+ *
+ * @param attName
+ */
+ protected void getChimeraAttributes(String attName)
+ {
+ jmb.copyStructureAttributesToFeatures(attName, getAlignmentPanel());
+ }
+
+ /**
+ * Send a command to Chimera to create residue attributes for Jalview features
+ * <p>
+ * The syntax is: setattr r <attName> <attValue> <atomSpec>
+ * <p>
+ * For example: setattr r jv:chain "Ferredoxin-1, Chloroplastic" #0:94.A
+ */
+ protected void sendFeaturesToChimera()
+ {
+ jmb.sendFeaturesToViewer(getAlignmentPanel());
}
/**
*/
void initChimera()
{
- Desktop.addInternalFrame(this, jmb.getViewerTitle("Chimera", true),
- getBounds().width, getBounds().height);
+ jmb.setFinishedInit(false);
- jalview.gui.Desktop.addInternalFrame(this,
++ Desktop.addInternalFrame(this,
+ jmb.getViewerTitle(getViewerName(), true), getBounds().width,
+ getBounds().height);
if (!jmb.launchChimera())
{
jmb.startChimeraListener();
}
-
/**
- * If the list is not empty, add menu items for 'All' and each individual
- * chain to the "View | Show Chain" sub-menu. Multiple selections are allowed.
- *
- * @param chainNames
- */
- @Override
- void setChainMenuItems(List<String> chainNames)
- {
- chainMenu.removeAll();
- if (chainNames == null || chainNames.isEmpty())
- {
- return;
- }
- JMenuItem menuItem = new JMenuItem(
- MessageManager.getString("label.all"));
- menuItem.addActionListener(new ActionListener()
- {
- @Override
- public void actionPerformed(ActionEvent evt)
- {
- allChainsSelected = true;
- for (int i = 0; i < chainMenu.getItemCount(); i++)
- {
- if (chainMenu.getItem(i) instanceof JCheckBoxMenuItem)
- {
- ((JCheckBoxMenuItem) chainMenu.getItem(i)).setSelected(true);
- }
- }
- showSelectedChains();
- allChainsSelected = false;
- }
- });
-
- chainMenu.add(menuItem);
-
- for (String chainName : chainNames)
- {
- menuItem = new JCheckBoxMenuItem(chainName, true);
- menuItem.addItemListener(new ItemListener()
- {
- @Override
- public void itemStateChanged(ItemEvent evt)
- {
- if (!allChainsSelected)
- {
- showSelectedChains();
- }
- }
- });
-
- chainMenu.add(menuItem);
- }
- }
-
- /**
* Show only the selected chain(s) in the viewer
*/
@Override
{
try
{
- jalview.util.BrowserLauncher
+ BrowserLauncher
.openURL("https://www.cgl.ucsf.edu/chimera/docs/UsersGuide");
-- } catch (Exception ex)
++ } catch (IOException ex)
{
}
}
}
@Override
- protected AAStructureBindingModel getBindingModel()
+ protected String getViewerName()
{
- return jmb;
+ return "Chimera";
+ }
++
++ @Override
++ public void updateTitleAndMenus()
++ {
++ super.updateTitleAndMenus();
++ viewerActionMenu.setVisible(true);
+ }
}
public void testBuildColourCommands()
{
- Map<Color, SortedMap<Integer, Map<String, List<int[]>>>> map = new LinkedHashMap<Color, SortedMap<Integer, Map<String, List<int[]>>>>();
+ 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");
+ 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");
// Colours should appear in the Chimera command in the order in which
- // they were added; within colour, by model, by chain, and positions as
- // added
+ // they were added; within colour, by model, by chain, ranges in start order
String command = ChimeraCommands.buildColourCommands(map).get(0);
assertEquals(
- "color #0000ff #0:2-5.A,9-23.A,7.B|#1:1.A,4-7.B; color #ffff00 #1:8.A,3-5.A; color #ff0000 #0:3-5.A",
- command);
+ command,
+ "color #0000ff #0:2-5.A,9-23.A,7.B|#1:1.A,4-7.B; color #ffff00 #1:3-5.A,8.A; color #ff0000 #0:3-9.A");
+ }
+
+ @Test(groups = { "Functional" })
+ public void testBuildSetAttributeCommands()
+ {
+ /*
+ * make a map of { featureType, {featureValue, {residue range specification } } }
+ */
+ Map<String, Map<Object, AtomSpecModel>> featuresMap = new LinkedHashMap<String, Map<Object, AtomSpecModel>>();
+ Map<Object, AtomSpecModel> featureValues = new HashMap<Object, AtomSpecModel>();
+
+ /*
+ * start with just one feature/value...
+ */
+ featuresMap.put("chain", featureValues);
- ChimeraCommands.addRange(featureValues, "X", 0, 8, 20, "A");
++ ChimeraCommands.addColourRange(featureValues, "X", 0, 8, 20, "A");
+
+ List<String> commands = ChimeraCommands
+ .buildSetAttributeCommands(featuresMap);
+ assertEquals(1, commands.size());
+
+ /*
+ * feature name gets a jv_ namespace prefix
+ * feature value is quoted in case it contains spaces
+ */
+ assertEquals(commands.get(0), "setattr r jv_chain \"X\" #0:8-20.A");
+
+ // add same feature value, overlapping range
- ChimeraCommands.addRange(featureValues, "X", 0, 3, 9, "A");
++ ChimeraCommands.addColourRange(featureValues, "X", 0, 3, 9, "A");
+ // same feature value, contiguous range
- ChimeraCommands.addRange(featureValues, "X", 0, 21, 25, "A");
++ ChimeraCommands.addColourRange(featureValues, "X", 0, 21, 25, "A");
+ commands = ChimeraCommands.buildSetAttributeCommands(featuresMap);
+ assertEquals(1, commands.size());
+ assertEquals(commands.get(0), "setattr r jv_chain \"X\" #0:3-25.A");
+
+ // same feature value and model, different chain
- ChimeraCommands.addRange(featureValues, "X", 0, 21, 25, "B");
++ ChimeraCommands.addColourRange(featureValues, "X", 0, 21, 25, "B");
+ // same feature value and chain, different model
- ChimeraCommands.addRange(featureValues, "X", 1, 26, 30, "A");
++ ChimeraCommands.addColourRange(featureValues, "X", 1, 26, 30, "A");
+ commands = ChimeraCommands.buildSetAttributeCommands(featuresMap);
+ assertEquals(1, commands.size());
+ assertEquals(commands.get(0),
+ "setattr r jv_chain \"X\" #0:3-25.A,21-25.B|#1:26-30.A");
+
+ // same feature, different value
- ChimeraCommands.addRange(featureValues, "Y", 0, 40, 50, "A");
++ ChimeraCommands.addColourRange(featureValues, "Y", 0, 40, 50, "A");
+ commands = ChimeraCommands.buildSetAttributeCommands(featuresMap);
+ assertEquals(2, commands.size());
+ // commands are ordered by feature type but not by value
+ // so use contains to test for the expected command:
+ assertTrue(commands
+ .contains("setattr r jv_chain \"X\" #0:3-25.A,21-25.B|#1:26-30.A"));
+ assertTrue(commands.contains("setattr r jv_chain \"Y\" #0:40-50.A"));
+
+ featuresMap.clear();
+ featureValues.clear();
+ featuresMap.put("side-chain binding!", featureValues);
- ChimeraCommands.addRange(featureValues, "metal ion!", 0, 7, 15, "A");
++ ChimeraCommands.addColourRange(featureValues, "metal ion!", 0, 7, 15,
++ "A");
+ // feature names are sanitised to change space or hyphen to underscore
+ commands = ChimeraCommands.buildSetAttributeCommands(featuresMap);
+ assertTrue(commands
+ .contains("setattr r jv_side_chain_binding_ \"metal ion!\" #0:7-15.A"));
+ }
+
+ /**
+ * Tests for the method that prefixes and sanitises a feature name so it can
+ * be used as a valid, namespaced attribute name in Chimera
+ */
+ @Test(groups = { "Functional" })
+ public void testMakeAttributeName()
+ {
+ assertEquals(ChimeraCommands.makeAttributeName(null), "jv_");
+ assertEquals(ChimeraCommands.makeAttributeName(""), "jv_");
+ assertEquals(ChimeraCommands.makeAttributeName("helix"), "jv_helix");
+ assertEquals(ChimeraCommands.makeAttributeName("Hello World 24"),
+ "jv_Hello_World_24");
+ assertEquals(
+ ChimeraCommands.makeAttributeName("!this is-a_very*{odd(name"),
+ "jv__this_is_a_very__odd_name");
+ // name ending in color gets underscore appended
+ assertEquals(ChimeraCommands.makeAttributeName("helixColor"),
+ "jv_helixColor_");
}
}
*/
public class AnnotationChooserTest
{
++ /*
++ * number of automatically computed annotation rows
++ * (Conservation, Quality, Consensus, Occupancy)
++ */
++ private static final int AUTOCALCD = 4;
@BeforeClass(alwaysRun = true)
public void setUpJvOptionPane()
types = AnnotationChooser.getAnnotationTypes(
parentPanel.getAlignment(), false);
-- assertEquals("Not six annotation types", 6, types.size());
++ assertEquals("Not six annotation types", 7, types.size());
assertTrue("IUPRED missing", types.contains("IUPRED"));
assertTrue("JMol missing", types.contains("JMol"));
assertTrue("Beauty missing", types.contains("Beauty"));
assertTrue("Consensus missing", types.contains("Consensus"));
assertTrue("Quality missing", types.contains("Quality"));
assertTrue("Conservation missing", types.contains("Conservation"));
++ assertTrue("Occupancy missing", types.contains("Occupancy"));
}
/**
AlignmentAnnotation[] anns = parentPanel.getAlignment()
.getAlignmentAnnotation();
-- assertTrue(anns[5].visible); // JMol for seq3
-- assertTrue(anns[7].visible); // JMol for seq1
++ assertTrue(anns[AUTOCALCD + 2].visible); // JMol for seq3
++ assertTrue(anns[AUTOCALCD + 4].visible); // JMol for seq1
setSelected(getTypeCheckbox("JMol"), true);
assertTrue(anns[0].visible); // Conservation
assertTrue(anns[1].visible); // Quality
assertTrue(anns[2].visible); // Consensus
-- assertTrue(anns[3].visible); // IUPred for seq0
-- assertTrue(anns[4].visible); // Beauty
-- assertFalse(anns[5].visible); // JMol for seq3 - not selected but hidden
-- assertTrue(anns[6].visible); // IUPRED for seq2
-- assertFalse(anns[7].visible); // JMol for seq1 - selected and hidden
++ assertTrue(anns[3].visible); // Occupancy
++ assertTrue(anns[4].visible); // IUPred for seq0
++ assertTrue(anns[5].visible); // Beauty
++ assertFalse(anns[6].visible); // JMol for seq3 - not selected but hidden
++ assertTrue(anns[7].visible); // IUPRED for seq2
++ assertFalse(anns[8].visible); // JMol for seq1 - selected and hidden
}
/**
AlignmentAnnotation[] anns = parentPanel.getAlignment()
.getAlignmentAnnotation();
-- assertTrue(anns[7].visible); // JMol for seq1
++ assertTrue(anns[AUTOCALCD + 4].visible); // JMol for seq1
setSelected(getTypeCheckbox("JMol"), true);
assertTrue(anns[0].visible); // Conservation
assertTrue(anns[1].visible); // Quality
assertTrue(anns[2].visible); // Consensus
-- assertTrue(anns[3].visible); // IUPred for seq0
-- assertTrue(anns[4].visible); // Beauty
-- assertTrue(anns[5].visible); // JMol for seq3 not in selection group
-- assertTrue(anns[6].visible); // IUPRED for seq2
-- assertFalse(anns[7].visible); // JMol for seq1 in selection group
++ assertTrue(anns[3].visible); // Occupancy
++ assertTrue(anns[4].visible); // IUPred for seq0
++ assertTrue(anns[5].visible); // Beauty
++ assertTrue(anns[6].visible); // JMol for seq3 not in selection group
++ assertTrue(anns[7].visible); // IUPRED for seq2
++ assertFalse(anns[8].visible); // JMol for seq1 in selection group
}
/**
// select JMol - all hidden
setSelected(typeCheckbox, true);
-- assertFalse(anns[5].visible); // JMol for seq3
-- assertFalse(anns[7].visible); // JMol for seq1
++ assertFalse(anns[AUTOCALCD + 2].visible); // JMol for seq3
++ assertFalse(anns[AUTOCALCD + 4].visible); // JMol for seq1
// deselect JMol - all unhidden
setSelected(typeCheckbox, false);
assertTrue(anns[0].visible); // Conservation
assertTrue(anns[1].visible); // Quality
assertTrue(anns[2].visible); // Consensus
-- assertTrue(anns[3].visible); // IUPred for seq0
-- assertTrue(anns[4].visible); // Beauty
-- assertTrue(anns[5].visible); // JMol for seq3
-- assertTrue(anns[6].visible); // IUPRED for seq2
-- assertTrue(anns[7].visible); // JMol for seq1
++ assertTrue(anns[3].visible); // Occupancy
++ assertTrue(anns[4].visible); // IUPred for seq0
++ assertTrue(anns[5].visible); // Beauty
++ assertTrue(anns[6].visible); // JMol for seq3
++ assertTrue(anns[7].visible); // IUPRED for seq2
++ assertTrue(anns[8].visible); // JMol for seq1
}
/**
setSelected(allSequencesCheckbox, true);
setSelected(hideCheckbox, true);
setSelected(getTypeCheckbox("JMol"), true);
-- assertFalse(anns[5].visible); // JMol for seq3
-- assertFalse(anns[7].visible); // JMol for seq1
++ assertFalse(anns[AUTOCALCD + 2].visible); // JMol for seq3
++ assertFalse(anns[AUTOCALCD + 4].visible); // JMol for seq1
// ...now show them...
setSelected(showCheckbox, true);
assertTrue(anns[0].visible); // Conservation
assertTrue(anns[1].visible); // Quality
assertTrue(anns[2].visible); // Consensus
-- assertTrue(anns[3].visible); // IUPred for seq0
-- assertTrue(anns[4].visible); // Beauty
-- assertTrue(anns[5].visible); // JMol for seq3
-- assertTrue(anns[6].visible); // IUPRED for seq2
-- assertTrue(anns[7].visible); // JMol for seq1
++ assertTrue(anns[3].visible); // Occupancy
++ assertTrue(anns[4].visible); // IUPred for seq0
++ assertTrue(anns[5].visible); // Beauty
++ assertTrue(anns[6].visible); // JMol for seq3
++ assertTrue(anns[7].visible); // IUPRED for seq2
++ assertTrue(anns[8].visible); // JMol for seq1
}
/**
setSelected(hideCheckbox, true);
setSelected(getTypeCheckbox("JMol"), true);
-- assertTrue(anns[5].visible); // JMol for seq3
-- assertFalse(anns[7].visible); // JMol for seq1
++ assertTrue(anns[AUTOCALCD + 2].visible); // JMol for seq3
++ assertFalse(anns[AUTOCALCD + 4].visible); // JMol for seq1
// ...now show them...
setSelected(showCheckbox, true);
assertTrue(anns[0].visible); // Conservation
assertTrue(anns[1].visible); // Quality
assertTrue(anns[2].visible); // Consensus
-- assertTrue(anns[3].visible); // IUPred for seq0
-- assertTrue(anns[4].visible); // Beauty
-- assertTrue(anns[5].visible); // JMol for seq3
-- assertTrue(anns[6].visible); // IUPRED for seq2
-- assertTrue(anns[7].visible); // JMol for seq1
++ assertTrue(anns[3].visible); // Occupancy
++ assertTrue(anns[4].visible); // IUPred for seq0
++ assertTrue(anns[5].visible); // Beauty
++ assertTrue(anns[6].visible); // JMol for seq3
++ assertTrue(anns[7].visible); // IUPRED for seq2
++ assertTrue(anns[8].visible); // JMol for seq1
}
/**
final Checkbox typeCheckbox = getTypeCheckbox("JMol");
// select JMol - all shown
setSelected(typeCheckbox, true);
-- assertTrue(anns[5].visible); // JMol for seq3
-- assertTrue(anns[7].visible); // JMol for seq1
++ assertTrue(anns[AUTOCALCD + 2].visible); // JMol for seq3
++ assertTrue(anns[AUTOCALCD + 4].visible); // JMol for seq1
// deselect JMol - all hidden
setSelected(typeCheckbox, false);
assertTrue(anns[0].visible); // Conservation
assertTrue(anns[1].visible); // Quality
assertTrue(anns[2].visible); // Consensus
-- assertTrue(anns[3].visible); // IUPred for seq0
-- assertTrue(anns[4].visible); // Beauty
-- assertFalse(anns[5].visible); // JMol for seq3
-- assertTrue(anns[6].visible); // IUPRED for seq2
-- assertFalse(anns[7].visible); // JMol for seq1
++ assertTrue(anns[3].visible); // Occupancy
++ assertTrue(anns[4].visible); // IUPred for seq0
++ assertTrue(anns[5].visible); // Beauty
++ assertFalse(anns[6].visible); // JMol for seq3
++ assertTrue(anns[7].visible); // IUPRED for seq2
++ assertFalse(anns[8].visible); // JMol for seq1
}
/**
// select JMol - should remain visible
setSelected(getTypeCheckbox("JMol"), true);
-- assertTrue(anns[5].visible); // JMol for seq3
-- assertTrue(anns[7].visible); // JMol for seq1
++ assertTrue(anns[AUTOCALCD + 2].visible); // JMol for seq3
++ assertTrue(anns[AUTOCALCD + 4].visible); // JMol for seq1
// deselect JMol - should be hidden for selected sequences only
setSelected(getTypeCheckbox("JMol"), false);
assertTrue(anns[0].visible); // Conservation
assertTrue(anns[1].visible); // Quality
assertTrue(anns[2].visible); // Consensus
-- assertTrue(anns[3].visible); // IUPred for seq0
-- assertTrue(anns[4].visible); // Beauty
-- assertTrue(anns[5].visible); // JMol for seq3 not in selection group
-- assertTrue(anns[6].visible); // IUPRED for seq2
-- assertFalse(anns[7].visible); // JMol for seq1 in selection group
++ assertTrue(anns[3].visible); // Occupancy
++ assertTrue(anns[4].visible); // IUPred for seq0
++ assertTrue(anns[5].visible); // Beauty
++ assertTrue(anns[6].visible); // JMol for seq3 not in selection group
++ assertTrue(anns[7].visible); // IUPRED for seq2
++ assertFalse(anns[8].visible); // JMol for seq1 in selection group
}
/**
AlignmentAnnotation[] anns = parentPanel.getAlignment()
.getAlignmentAnnotation();
-- // remember 3 annotations to skip (Conservation/Quality/Consensus)
-- assertFalse(testee.isInActionScope(anns[3]));
-- assertFalse(testee.isInActionScope(anns[4]));
-- assertFalse(testee.isInActionScope(anns[5]));
-- assertTrue(testee.isInActionScope(anns[6]));
-- assertTrue(testee.isInActionScope(anns[7]));
++ assertFalse(testee.isInActionScope(anns[AUTOCALCD]));
++ assertFalse(testee.isInActionScope(anns[AUTOCALCD + 1]));
++ assertFalse(testee.isInActionScope(anns[AUTOCALCD + 2]));
++ assertTrue(testee.isInActionScope(anns[AUTOCALCD + 3]));
++ assertTrue(testee.isInActionScope(anns[AUTOCALCD + 4]));
}
/**
AlignmentAnnotation[] anns = parentPanel.getAlignment()
.getAlignmentAnnotation();
-- // remember 3 annotations to skip (Conservation/Quality/Consensus)
-- assertTrue(testee.isInActionScope(anns[3]));
-- assertTrue(testee.isInActionScope(anns[4]));
-- assertTrue(testee.isInActionScope(anns[5]));
-- assertFalse(testee.isInActionScope(anns[6]));
-- assertFalse(testee.isInActionScope(anns[7]));
++ assertTrue(testee.isInActionScope(anns[AUTOCALCD]));
++ assertTrue(testee.isInActionScope(anns[AUTOCALCD + 1]));
++ assertTrue(testee.isInActionScope(anns[AUTOCALCD + 2]));
++ assertFalse(testee.isInActionScope(anns[AUTOCALCD + 3]));
++ assertFalse(testee.isInActionScope(anns[AUTOCALCD + 4]));
}
/**
assertTrue(anns[0].visible); // Conservation
assertTrue(anns[1].visible); // Quality
assertTrue(anns[2].visible); // Consensus
-- assertFalse(anns[3].visible); // IUPRED
-- assertTrue(anns[4].visible); // Beauty (not seq-related)
-- assertFalse(anns[5].visible); // JMol
-- assertFalse(anns[6].visible); // IUPRED
-- assertFalse(anns[7].visible); // JMol
++ assertTrue(anns[3].visible); // Occupancy
++ assertFalse(anns[4].visible); // IUPRED
++ assertTrue(anns[5].visible); // Beauty (not seq-related)
++ assertFalse(anns[6].visible); // JMol
++ assertFalse(anns[7].visible); // IUPRED
++ assertFalse(anns[8].visible); // JMol
// reset - should all be visible
testee.resetOriginalState();