X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fext%2Fjmol%2FJalviewJmolBinding.java;fp=src%2Fjalview%2Fext%2Fjmol%2FJalviewJmolBinding.java;h=cdd137b8e2bc3946785d9b6c28361553b8ec4a17;hb=3bc2fbe640abb0d8941aead117c9624dd16773a3;hp=deadbfce17c53d71afed5c1cabd7fe805d6ed9ae;hpb=a0f81f2688004be19c4baaf9c3ddb0813bbc209e;p=jalview.git diff --git a/src/jalview/ext/jmol/JalviewJmolBinding.java b/src/jalview/ext/jmol/JalviewJmolBinding.java index deadbfc..cdd137b 100644 --- a/src/jalview/ext/jmol/JalviewJmolBinding.java +++ b/src/jalview/ext/jmol/JalviewJmolBinding.java @@ -50,11 +50,10 @@ import jalview.datamodel.SequenceI; import jalview.io.AppletFormatAdapter; import jalview.schemes.ColourSchemeI; import jalview.schemes.ResidueProperties; -import jalview.structure.StructureMapping; +import jalview.structure.AtomSpec; import jalview.structure.StructureMappingcommandSet; import jalview.structure.StructureSelectionManager; import jalview.structures.models.AAStructureBindingModel; -import jalview.util.MessageManager; public abstract class JalviewJmolBinding extends AAStructureBindingModel implements JmolStatusListener, JmolSelectionListener, @@ -243,47 +242,31 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel { hiddenCols }); } + /** + * Construct and send a command to align structures against a reference + * structure, based on one or more sequence alignments + * + * @param _alignment + * an array of alignments to process + * @param _refStructure + * an array of corresponding reference structures (index into pdb + * file array); if a negative value is passed, the first PDB file + * mapped to an alignment sequence is used as the reference for + * superposition + * @param _hiddenCols + * an array of corresponding hidden columns for each alignment + */ public void superposeStructures(AlignmentI[] _alignment, int[] _refStructure, ColumnSelection[] _hiddenCols) { - assert (_alignment.length == _refStructure.length && _alignment.length != _hiddenCols.length); - String[] files = getPdbFile(); - // check to see if we are still waiting for Jmol files - long starttime = System.currentTimeMillis(); - boolean waiting = true; - do - { - waiting = false; - for (String file : files) - { - try - { - // HACK - in Jalview 2.8 this call may not be threadsafe so we catch - // every possible exception - StructureMapping[] sm = getSsm().getMapping(file); - if (sm == null || sm.length == 0) - { - waiting = true; - } - } catch (Exception x) - { - waiting = true; - } catch (Error q) - { - waiting = true; - } - } - // we wait around for a reasonable time before we give up - } while (waiting - && System.currentTimeMillis() < (10000 + 1000 * files.length + starttime)); - if (waiting) + + if (!waitForFileLoad(files)) { - System.err - .println("RUNTIME PROBLEM: Jmol seems to be taking a long time to process all the structures."); return; } - StringBuffer selectioncom = new StringBuffer(); + + StringBuilder selectioncom = new StringBuilder(256); // In principle - nSeconds specifies the speed of animation for each // superposition - but is seems to behave weirdly, so we don't specify it. String nSeconds = " "; @@ -319,134 +302,78 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel + refStructure); refStructure = -1; } - if (refStructure < -1) - { - refStructure = -1; - } - StringBuffer command = new StringBuffer(); + /* + * 'matched' array will hold 'true' for visible alignment columns where + * all sequences have a residue with a mapping to the PDB structure + */ boolean matched[] = new boolean[alignment.getWidth()]; for (int m = 0; m < matched.length; m++) { - matched[m] = (hiddenCols != null) ? hiddenCols.isVisible(m) : true; } - int commonrpositions[][] = new int[files.length][alignment.getWidth()]; - String isel[] = new String[files.length]; - // reference structure - all others are superposed in it - String[] targetC = new String[files.length]; - String[] chainNames = new String[files.length]; - for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++) + SuperposeData[] structures = new SuperposeData[files.length]; + for (int f = 0; f < files.length; f++) { - StructureMapping[] mapping = getSsm().getMapping(files[pdbfnum]); - // RACE CONDITION - getMapping only returns Jmol loaded filenames once - // Jmol callback has completed. - if (mapping == null || mapping.length < 1) - { - throw new Error(MessageManager.getString("error.implementation_error_jmol_getting_data")); - } - int lastPos = -1; - final int sequenceCountForPdbFile = getSequence()[pdbfnum].length; - for (int s = 0; s < sequenceCountForPdbFile; s++) - { - for (int sp, m = 0; m < mapping.length; m++) - { - if (mapping[m].getSequence() == getSequence()[pdbfnum][s] - && (sp = alignment.findIndex(getSequence()[pdbfnum][s])) > -1) - { - if (refStructure == -1) - { - refStructure = pdbfnum; - } - SequenceI asp = alignment.getSequenceAt(sp); - for (int r = 0; r < matched.length; r++) - { - if (!matched[r]) - { - continue; - } - matched[r] = false; // assume this is not a good site - if (r >= asp.getLength()) - { - continue; - } - - if (jalview.util.Comparison.isGap(asp.getCharAt(r))) - { - // no mapping to gaps in sequence - continue; - } - int t = asp.findPosition(r); // sequence position - int apos = mapping[m].getAtomNum(t); - int pos = mapping[m].getPDBResNum(t); - - if (pos < 1 || pos == lastPos) - { - // can't align unmapped sequence - continue; - } - matched[r] = true; // this is a good ite - lastPos = pos; - // just record this residue position - commonrpositions[pdbfnum][r] = pos; - } - // create model selection suffix - isel[pdbfnum] = "/" + (pdbfnum + 1) + ".1"; - if (mapping[m].getChain() == null - || mapping[m].getChain().trim().length() == 0) - { - targetC[pdbfnum] = ""; - } - else - { - targetC[pdbfnum] = ":" + mapping[m].getChain(); - } - chainNames[pdbfnum] = mapping[m].getPdbId() - + targetC[pdbfnum]; - // move on to next pdb file - s = getSequence()[pdbfnum].length; - break; - } - } - } + structures[f] = new SuperposeData(alignment.getWidth()); } - // TODO: consider bailing if nmatched less than 4 because superposition - // not - // well defined. - // TODO: refactor superposable position search (above) from jmol selection - // construction (below) + /* + * Calculate the superposable alignment columns ('matched'), and the + * corresponding structure residue positions (structures.pdbResNo) + */ + int candidateRefStructure = findSuperposableResidues(alignment, + matched, structures); + if (refStructure < 0) + { + /* + * If no reference structure was specified, pick the first one that has + * a mapping in the alignment + */ + refStructure = candidateRefStructure; + } String[] selcom = new String[files.length]; int nmatched = 0; - // generate select statements to select regions to superimpose structures + for (boolean b : matched) + { + if (b) + { + nmatched++; + } + } + if (nmatched < 4) + { + // TODO: bail out here because superposition illdefined? + } + + /* + * generate select statements to select regions to superimpose structures + */ { for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++) { - String chainCd = targetC[pdbfnum]; + String chainCd = ":" + structures[pdbfnum].chain; int lpos = -1; boolean run = false; - StringBuffer molsel = new StringBuffer(); + StringBuilder molsel = new StringBuilder(); molsel.append("{"); for (int r = 0; r < matched.length; r++) { if (matched[r]) { - if (pdbfnum == 0) - { - nmatched++; - } - if (lpos != commonrpositions[pdbfnum][r] - 1) + int pdbResNo = structures[pdbfnum].pdbResNo[r]; + if (lpos != pdbResNo - 1) { // discontinuity if (lpos != -1) { molsel.append(lpos); molsel.append(chainCd); - // molsel.append("} {"); molsel.append("|"); } + run = false; } else { @@ -459,11 +386,12 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel } run = true; } - lpos = commonrpositions[pdbfnum][r]; - // molsel.append(lpos); + lpos = pdbResNo; } } - // add final selection phrase + /* + * add final selection phrase + */ if (lpos != -1) { molsel.append(lpos); @@ -490,6 +418,7 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel } } } + StringBuilder command = new StringBuilder(256); for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++) { if (pdbfnum == refStructure || selcom[pdbfnum] == null @@ -499,23 +428,23 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel } command.append("echo "); command.append("\"Superposing ("); - command.append(chainNames[pdbfnum]); + command.append(structures[pdbfnum].pdbId); command.append(") against reference ("); - command.append(chainNames[refStructure]); + command.append(structures[refStructure].pdbId); command.append(")\";\ncompare " + nSeconds); command.append("{"); - command.append(1 + pdbfnum); + command.append(Integer.toString(1 + pdbfnum)); command.append(".1} {"); - command.append(1 + refStructure); + command.append(Integer.toString(1 + refStructure)); // conformation=1 excludes alternate locations for CA (JAL-1757) command.append(".1} SUBSET {(*.CA | *.P) and conformation=1} ATOMS "); - // form the matched pair strings - String sep = ""; - for (int s = 0; s < 2; s++) - { - command.append(selcom[(s == 0 ? pdbfnum : refStructure)]); - } + // for (int s = 0; s < 2; s++) + // { + // command.append(selcom[(s == 0 ? pdbfnum : refStructure)]); + // } + command.append(selcom[pdbfnum]); + command.append(selcom[refStructure]); command.append(" ROTATE TRANSLATE;\n"); } if (selectioncom.length() > 0) @@ -524,10 +453,11 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel evalStateCommand("select *; cartoons off; backbone; select (" + selectioncom.toString() + "); cartoons; "); // selcom.append("; ribbons; "); + String cmdString = command.toString(); System.out - .println("Superimpose command(s):\n" + command.toString()); +.println("Superimpose command(s):\n" + cmdString); - evalStateCommand(command.toString()); + evalStateCommand(cmdString); } } if (selectioncom.length() > 0) @@ -703,6 +633,7 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel // //////////////////////////////// // /StructureListener + @Override public synchronized String[] getPdbFile() { if (viewer == null) @@ -786,6 +717,22 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel jmolpopup.show(x, y); } + /** + * Highlight zero, one or more atoms on the structure + */ + @Override + public void highlightAtoms(List atoms) + { + if (atoms != null) + { + for (AtomSpec atom : atoms) + { + highlightAtom(atom.getAtomIndex(), atom.getPdbResNum(), + atom.getChain(), atom.getPdbFile()); + } + } + } + // jmol/ssm only public void highlightAtom(int atomIndex, int pdbResNum, String chain, String pdbfile)