From: gmungoc Date: Wed, 23 Nov 2016 10:03:07 +0000 (+0000) Subject: Merge branch 'develop' into features/JAL-2295setChimeraAttributes X-Git-Tag: Release_2_11_0~62^2~42 X-Git-Url: http://source.jalview.org/gitweb/?a=commitdiff_plain;h=7d8f40032746ee633dd980d5609c4d517a40421a;p=jalview.git Merge branch 'develop' into features/JAL-2295setChimeraAttributes Conflicts: src/jalview/structure/StructureSelectionManager.java --- 7d8f40032746ee633dd980d5609c4d517a40421a diff --cc src/jalview/ext/rbvi/chimera/JalviewChimeraBinding.java index 7e70fef,4a9bf5f..cc1de6a --- a/src/jalview/ext/rbvi/chimera/JalviewChimeraBinding.java +++ b/src/jalview/ext/rbvi/chimera/JalviewChimeraBinding.java @@@ -27,9 -27,6 +27,9 @@@ import jalview.bin.Cache import jalview.datamodel.AlignmentI; import jalview.datamodel.ColumnSelection; import jalview.datamodel.PDBEntry; ++import jalview.datamodel.SearchResultMatchI; +import jalview.datamodel.SearchResults; - import jalview.datamodel.SearchResults.Match; +import jalview.datamodel.SequenceFeature; import jalview.datamodel.SequenceI; import jalview.httpserver.AbstractRequestHandler; import jalview.schemes.ColourSchemeI; @@@ -1080,214 -1098,13 +1080,214 @@@ public abstract class JalviewChimeraBin } } + /** + * Constructs and send commands to Chimera to set attributes on residues for + * features visible in Jalview + * + * @param avp + */ + public void sendFeaturesToViewer(AlignmentViewPanel avp) + { + // TODO refactor as required to pull up to an interface + AlignmentI alignment = avp.getAlignment(); + FeatureRenderer fr = getFeatureRenderer(avp); - @Override - public List getChainNames() + /* + * fr is null if feature display is turned off + */ + if (fr == null) + { + return; + } + + String[] files = getPdbFile(); + if (files == null) + { + return; + } + + StructureMappingcommandSet commandSet = ChimeraCommands + .getSetAttributeCommandsForFeatures(getSsm(), files, + getSequence(), fr, alignment); + String[] commands = commandSet.commands; + if (commands.length > 10) + { + sendCommandsByFile(commands); + } + else + { + for (String command : commands) + { + sendAsynchronousCommand(command, null); + } + } + } + + /** + * Write commands to a temporary file, and send a command to Chimera to open + * the file as a commands script. For use when sending a large number of + * separate commands would overload the REST interface mechanism. + * + * @param commands + */ + protected void sendCommandsByFile(String[] commands) { - return chainNames; + try + { + File tmp = File.createTempFile("chim", ".com"); + tmp.deleteOnExit(); + PrintWriter out = new PrintWriter(new FileOutputStream(tmp)); + for (String command : commands) + { + out.println(command); + } + out.flush(); + out.close(); + String path = tmp.getAbsolutePath(); + sendAsynchronousCommand("open cmd:" + path, null); + } catch (IOException e) + { + System.err + .println("Sending commands to Chimera via file failed with " + + 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 + */ + // this alternative command + // list residues spec ':*/attName' attr attName + // doesn't report 'None' values (which is good), but + // fails for 'average.bfactor' (which is bad): + + String cmd = "list residues attr '" + attName + "'"; + List residues = sendChimeraCommand(cmd, true); + + boolean featureAdded = createFeaturesForAttributes(attName, residues); + if (featureAdded) + { + alignmentPanel.getFeatureRenderer().featuresAdded(); + } + } + + /** + * Create features in Jalview for the given attribute name and structure + * residues. + * + *
 +   * The residue list should be 0, 1 or more reply lines of the format: 
 +   *     residue id #0:5.A isHelix -155.000836316 index 5 
 +   * or 
 +   *     residue id #0:6.A isHelix None
 +   * 
+ * + * @param attName + * @param residues + * @return + */ + protected boolean createFeaturesForAttributes(String attName, + List residues) + { + boolean featureAdded = false; + String featureGroup = getViewerFeatureGroup(); + + for (String residue : residues) + { + AtomSpec spec = null; + String[] tokens = residue.split(" "); + if (tokens.length < 5) + { + continue; + } + String atomSpec = tokens[2]; + String attValue = tokens[4]; + + /* + * ignore 'None' (e.g. for phi) or 'False' (e.g. for isHelix) + */ + if ("None".equalsIgnoreCase(attValue) + || "False".equalsIgnoreCase(attValue)) + { + continue; + } + + try + { + spec = AtomSpec.fromChimeraAtomspec(atomSpec); + } catch (IllegalArgumentException e) + { + System.err.println("Problem parsing atomspec " + atomSpec); + continue; + } + + String chainId = spec.getChain(); + String description = attValue; + float score = Float.NaN; + try + { + score = Float.valueOf(attValue); + description = chainId; + } catch (NumberFormatException e) + { + // was not a float value + } + + String pdbFile = getPdbFileForModel(spec.getModelNumber()); + spec.setPdbFile(pdbFile); + + List atoms = Collections.singletonList(spec); + + /* + * locate the mapped position in the alignment (if any) + */ + SearchResults sr = getSsm() + .findAlignmentPositionsForStructurePositions(atoms); + + /* + * expect one matched alignment position, or none + * (if the structure position is not mapped) + */ - for (Match m : sr.getResults()) ++ for (SearchResultMatchI m : sr.getResults()) + { + SequenceI seq = m.getSequence(); + int start = m.getStart(); + int end = m.getEnd(); + SequenceFeature sf = new SequenceFeature(attName, description, + start, end, score, featureGroup); + // todo: should SequenceFeature have an explicit property for chain? + // note: repeating the action shouldn't duplicate features + featureAdded |= seq.addSequenceFeature(sf); + } + } + return featureAdded; + } + + /** + * 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_FEATURE_GROUP; + } + + public Hashtable getChainFile() { return chainFile; diff --cc src/jalview/structure/StructureSelectionManager.java index c8708bd,b3968a3..27ff242 --- a/src/jalview/structure/StructureSelectionManager.java +++ b/src/jalview/structure/StructureSelectionManager.java @@@ -805,28 -806,7 +806,28 @@@ public class StructureSelectionManage return; } - SearchResults results = findAlignmentPositionsForStructurePositions(atoms); - SearchResultsI results = new SearchResults(); ++ SearchResultsI results = findAlignmentPositionsForStructurePositions(atoms); + for (Object li : listeners) + { + if (li instanceof SequenceListener) + { + ((SequenceListener) li).highlightSequence(results); + } + } + } + + /** + * Constructs a SearchResults object holding regions (if any) in the Jalview + * alignment which have a mapping to the structure viewer positions in the + * supplied list + * + * @param atoms + * @return + */ + public SearchResults findAlignmentPositionsForStructurePositions( + List atoms) + { + SearchResults results = new SearchResults(); for (AtomSpec atom : atoms) { SequenceI lastseq = null;