import jalview.datamodel.AlignmentI;
import jalview.datamodel.ColumnSelection;
import jalview.datamodel.PDBEntry;
+import jalview.datamodel.SequenceFeature;
import jalview.datamodel.SequenceI;
import jalview.httpserver.AbstractRequestHandler;
import jalview.schemes.ColourSchemeI;
import java.io.PrintWriter;
import java.net.BindException;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
*/
private Map<String, List<ChimeraModel>> chimeraMaps = new LinkedHashMap<String, List<ChimeraModel>>();
- /*
- * the default or current model displayed if the model cannot be identified
- * from the selection message
- */
- private int frameNo = 0;
-
- private String lastCommand;
-
String lastHighlightCommand;
/*
chimeraListener.shutdown();
chimeraListener = null;
}
- lastCommand = null;
viewer = null;
releaseUIResources();
}
/**
- * Send a command to Chimera, and optionally log and return any responses
+ * Send a command to Chimera, and optionally log and return any responses.
+ * <p>
+ * Does nothing, and returns null, if the command is the same as the last one
+ * sent [why?].
*
* @param command
* @param getResponse
}
List<String> reply = null;
viewerCommandHistory(false);
- if (lastCommand == null || !lastCommand.equals(command))
+ if (true /*lastCommand == null || !lastCommand.equals(command)*/)
{
// trim command or it may never find a match in the replyLog!!
List<String> lastReply = viewer.sendChimeraCommand(command.trim(),
}
}
viewerCommandHistory(true);
- lastCommand = command;
return reply;
}
* Parse model number, residue and chain for each selected position,
* formatted as #0:123.A or #1.2:87.B (#model.submodel:residue.chain)
*/
+ List<AtomSpec> atomSpecs = convertStructureResiduesToAlignment(selection);
+
+ /*
+ * Broadcast the selection (which may be empty, if the user just cleared all
+ * selections)
+ */
+ getSsm().mouseOverStructure(atomSpecs);
+ }
+
+ /**
+ * Converts a list of Chimera atomspecs to a list of AtomSpec representing the
+ * corresponding residues (if any) in Jalview
+ *
+ * @param structureSelection
+ * @return
+ */
+ protected List<AtomSpec> convertStructureResiduesToAlignment(
+ List<String> structureSelection)
+ {
List<AtomSpec> atomSpecs = new ArrayList<AtomSpec>();
- for (String atomSpec : selection)
+ for (String atomSpec : structureSelection)
{
int colonPos = atomSpec.indexOf(":");
if (colonPos == -1)
/*
* Work out the pdbfilename from the model number
*/
- String pdbfilename = modelFileNames[frameNo];
+ String pdbfilename = modelFileNames[0];
findfileloop: for (String pdbfile : this.chimeraMaps.keySet())
{
for (ChimeraModel cm : chimeraMaps.get(pdbfile))
}
atomSpecs.add(new AtomSpec(pdbfilename, chainId, pdbResNum, 0));
}
-
- /*
- * Broadcast the selection (which may be empty, if the user just cleared all
- * selections)
- */
- getSsm().mouseOverStructure(atomSpecs);
+ return atomSpecs;
}
private void log(String message)
*
* @param avp
*/
- public void sendFeaturesToChimera(AlignmentViewPanel avp)
+ public void sendFeaturesToViewer(AlignmentViewPanel avp)
{
+ // TODO refactor as required to pull up to an interface
AlignmentI alignment = avp.getAlignment();
FeatureRenderer fr = getFeatureRenderer(avp);
StructureMappingcommandSet commandSet = ChimeraCommands
.getSetAttributeCommandsForFeatures(getSsm(), files,
getSequence(), fr, alignment);
- // for (String command : commandSet.commands)
- // {
- // sendAsynchronousCommand(command, null);
- // }
- sendCommandsByFile(commandSet.commands);
+ String[] commands = commandSet.commands;
+ if (commands.length > 10)
+ {
+ sendCommandsByFile(commands);
+ }
+ else
+ {
+ for (String command : commands)
+ {
+ sendAsynchronousCommand(command, null);
+ }
+ }
}
/**
+ e.getMessage());
}
}
+
+ /**
+ * Get Chimera residues which have the named attribute, find the mapped
+ * positions in the Jalview sequence(s), and set as sequence features
+ *
+ * @param attName
+ * @param alignmentPanel
+ */
+ public void copyStructureAttributesToFeatures(String attName,
+ AlignmentViewPanel alignmentPanel)
+ {
+ // todo pull up to AAStructureBindingModel (and interface?)
+
+ /*
+ * ask Chimera to list residues with the attribute, reporting its value
+ */
+ String cmd = "list residues spec ':*/" + attName + "' attr " + attName;
+ List<String> residues = sendChimeraCommand(cmd, true);
+
+ /*
+ * TODO check if Jalview already has this feature name, if so give it a
+ * distinguishing prefix e.g. chim_
+ */
+ FeatureRenderer fr = alignmentPanel.getFeatureRenderer();
+ fr.getFeaturesDisplayed().getVisibleFeatureCount();
+
+ /*
+ * Expect 0, 1 or more reply lines of the format (chi2 is attName):
+ * residue id #0:5.A chi2 -155.000836316 index 5
+ */
+ Map<String, Map<SequenceI, List<Integer>>> attsMap = new HashMap<String, Map<SequenceI, List<Integer>>>();
+ for (String residue : residues)
+ {
+ String[] tokens = residue.split(" ");
+ if (tokens.length > 4)
+ {
+ String atomSpec = tokens[2];
+ String attValue = tokens[4];
+ // TODO find mapping of atomspec to Jalview residue if any
+ // build a map of { attValue, Map<SequenceI, List<Integer>> }
+ // sort the integer lists
+ // and create a feature for each contiguous integer range
+ SequenceI seq = null; // mapped-to sequence
+ int seqPos = 0; // mapped-to sequence position
+
+ /*
+ * record attribute value / sequence / sequence position
+ */
+ Map<SequenceI, List<Integer>> seqMap = attsMap.get(attValue);
+ if (seqMap == null)
+ {
+ seqMap = new HashMap<SequenceI, List<Integer>>();
+ attsMap.put(attValue, seqMap);
+ }
+ List<Integer> seqPositions = seqMap.get(seq);
+ if (seqPositions == null)
+ {
+ seqPositions = new ArrayList<Integer>();
+ seqMap.put(seq, seqPositions);
+ }
+ seqPositions.add(seqPos);
+ }
+ }
+
+ /*
+ * traverse values and sequences
+ */
+ for (String val : attsMap.keySet())
+ {
+ for (SequenceI seq : attsMap.get(val).keySet())
+ {
+ List<Integer> positions = attsMap.get(val).get(seq);
+ Collections.sort(positions);
+ // TODO find reusable code that compacts the list
+ List<int[]> ranges = null;// compacted list
+ for (int[] range : ranges)
+ {
+ float score = Float.NaN;
+ try
+ {
+ score = Float.valueOf(val);
+ } catch (NumberFormatException e)
+ {
+ // was not a float value
+ }
+ String featureGroup = getViewerFeatureGroup();
+ SequenceFeature sf = new SequenceFeature(attName, val, range[0],
+ range[1], score, featureGroup);
+ // note: repeating the action shouldn't duplicate features
+ seq.addSequenceFeature(sf);
+ }
+ }
+ }
+ }
+
+ /**
+ * Answers the feature group name to apply to features created in Jalview from
+ * Chimera attributes
+ *
+ * @return
+ */
+ protected String getViewerFeatureGroup()
+ {
+ // todo pull up to interface
+ return "Chimera";
+ }
}
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.AppletFormatAdapter;
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.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;
// TODO Auto-generated method stub
}
});
+
JMenuItem writeFeatures = new JMenuItem(
MessageManager.getString("label.create_chimera_attributes"));
writeFeatures.setToolTipText(MessageManager
}
});
viewerActionMenu.add(writeFeatures);
+
+ final JMenu fetchAttributes = new JMenu("Fetch Chimera attributes");
+ fetchAttributes
+ .setToolTipText("Copy Chimera attribute to Jalview feature");
+ 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());
}
/**
*/
protected void sendFeaturesToChimera()
{
- jmb.sendFeaturesToChimera(getAlignmentPanel());
+ jmb.sendFeaturesToViewer(getAlignmentPanel());
}
/**