X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fstructures%2Fmodels%2FAAStructureBindingModel.java;h=7d9674ea1c6220cabdec94cd6951908408324264;hb=03bc8848382795bda548083f0bc3202dfe6a9b8b;hp=d92c78a841182343b77f7d201ef6833f520a2adc;hpb=d87b55e45cc1e6a5b7df3865ded1b87a0e3dc7ff;p=jalview.git diff --git a/src/jalview/structures/models/AAStructureBindingModel.java b/src/jalview/structures/models/AAStructureBindingModel.java index d92c78a..7d9674e 100644 --- a/src/jalview/structures/models/AAStructureBindingModel.java +++ b/src/jalview/structures/models/AAStructureBindingModel.java @@ -29,6 +29,7 @@ import java.util.BitSet; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; +import java.util.Locale; import java.util.Map; import javax.swing.SwingUtilities; @@ -39,8 +40,9 @@ import jalview.api.FeatureRenderer; import jalview.api.SequenceRenderer; import jalview.api.StructureSelectionManagerProvider; import jalview.api.structures.JalviewStructureDisplayI; -import jalview.bin.Cache; +import jalview.bin.Console; import jalview.datamodel.AlignmentI; +import jalview.datamodel.ColumnSelection; import jalview.datamodel.HiddenColumns; import jalview.datamodel.MappedFeatures; import jalview.datamodel.PDBEntry; @@ -57,9 +59,9 @@ import jalview.schemes.ColourSchemeI; import jalview.schemes.ResidueProperties; import jalview.structure.AtomSpec; import jalview.structure.AtomSpecModel; -import jalview.structure.StructureCommand; import jalview.structure.StructureCommandI; import jalview.structure.StructureCommandsI; +import jalview.structure.StructureCommandsI.AtomSpecType; import jalview.structure.StructureListener; import jalview.structure.StructureMapping; import jalview.structure.StructureSelectionManager; @@ -68,9 +70,9 @@ import jalview.util.MessageManager; /** * - * A base class to hold common function for protein structure model binding. - * Initial version created by refactoring JMol and Chimera binding models, but - * other structure viewers could in principle be accommodated in future. + * A base class to hold common function for 3D structure model binding. Initial + * version created by refactoring JMol and Chimera binding models, but other + * structure viewers could in principle be accommodated in future. * * @author gmcarstairs * @@ -90,6 +92,9 @@ public abstract class AAStructureBindingModel public String chain = ""; + /** + * is the mapped sequence not protein ? + */ public boolean isRna; /* @@ -166,6 +171,9 @@ public abstract class AAStructureBindingModel protected boolean colourBySequence = true; + /** + * true if all sequences appear to be nucleotide + */ private boolean nucleotide; private boolean finishedInit = false; @@ -714,7 +722,7 @@ public abstract class AAStructureBindingModel structures[pdbfnum].chain = chain; } structures[pdbfnum].pdbId = mapping.getPdbId(); - structures[pdbfnum].isRna = theSequence.getRNA() != null; + structures[pdbfnum].isRna = !theSequence.isProtein(); /* * move on to next pdb file (ignore sequences for other chains @@ -863,21 +871,39 @@ public abstract class AAStructureBindingModel { AlignmentI alignment = view.getAlignment(); HiddenColumns hiddenCols = alignment.getHiddenColumns(); - /* * 'matched' bit i will be set for visible alignment columns i where * all sequences have a residue with a mapping to their PDB structure */ - BitSet matched = new BitSet(); final int width = alignment.getWidth(); - for (int m = 0; m < width; m++) + BitSet matched = new BitSet(); + ColumnSelection cs = view.getAlignViewport().getColumnSelection(); + // restrict to active column selection, if there is one + if (cs != null && cs.hasSelectedColumns() + && cs.getSelected().size() >= 4) { - if (hiddenCols == null || hiddenCols.isVisible(m)) + for (int s : cs.getSelected()) { - matched.set(m); + if (hiddenCols == null) + { + matched.set(s); + } + else + { + matched.set(hiddenCols.visibleToAbsoluteColumn(s)); + } + } + } + else + { + for (int m = 0; m < width; m++) + { + if (hiddenCols == null || hiddenCols.isVisible(m)) + { + matched.set(m); + } } } - AAStructureBindingModel.SuperposeData[] structures = new AAStructureBindingModel.SuperposeData[files.length]; for (int f = 0; f < files.length; f++) { @@ -917,6 +943,11 @@ public abstract class AAStructureBindingModel // todo better way to ensure synchronous than setting getReply true!! executeCommands(commandGenerator.showBackbone(), true, null); + AtomSpecType backbone = structures[refStructure].isRna + ? AtomSpecType.PHOSPHATE + : AtomSpecType.ALPHA; + List models = new ArrayList(); + models.add(refAtoms); /* * superpose each (other) structure to the reference in turn */ @@ -926,20 +957,27 @@ public abstract class AAStructureBindingModel { AtomSpecModel atomSpec = getAtomSpec(structures[i], matched); List commands = commandGenerator - .superposeStructures(refAtoms, atomSpec); + .superposeStructures(refAtoms, atomSpec, backbone); List replies = executeCommands(commands, true, null); for (String reply : replies) { // return this error (Chimera only) to the user - if (reply.toLowerCase().contains("unequal numbers of atoms")) + if (reply.toLowerCase(Locale.ROOT) + .contains("unequal numbers of atoms")) { error += "; " + reply; } } + models.add(atomSpec); } } + List finalView = commandGenerator + .centerViewOn(models); + if (finalView != null && finalView.size() > 0) + { + executeCommands(finalView, false, "Centered on Superposition"); + } } - return error; } @@ -981,8 +1019,8 @@ public abstract class AAStructureBindingModel // TODO: JAL-628 colour chains distinctly across all visible models - executeCommand(commandGenerator.colourByChain(), false, - COLOURING_STRUCTURES); + executeCommand(false, COLOURING_STRUCTURES, + commandGenerator.colourByChain()); } /** @@ -1040,34 +1078,72 @@ public abstract class AAStructureBindingModel public void setBackgroundColour(Color col) { StructureCommandI cmd = commandGenerator.setBackgroundColour(col); - executeCommand(cmd, false, null); + executeCommand(false, null, cmd); } /** - * Sends one command to the structure viewer. If {@code getReply} is true, the - * command is sent synchronously, otherwise in a deferred thread. - *

- * If a progress message is supplied, this is displayed before command - * execution, and removed afterwards. + * Execute one structure viewer command. If {@code getReply} is true, may + * optionally return one or more reply messages, else returns null. * * @param cmd * @param getReply + */ + protected abstract List executeCommand(StructureCommandI cmd, + boolean getReply); + + /** + * Executes one or more structure viewer commands + * + * @param commands + * @param getReply * @param msg - * @return */ - private List executeCommand(StructureCommandI cmd, + protected List executeCommands(List commands, boolean getReply, String msg) { + return executeCommand(getReply, msg, + commands.toArray(new StructureCommandI[commands.size()])); + } + + /** + * Executes one or more structure viewer commands, optionally returning the + * reply, and optionally showing a status message while the command is being + * executed. + *

+ * If a reply is wanted, the execution is done synchronously (waits), + * otherwise it is done in a separate thread (doesn't wait). WARNING: if you + * are sending commands that need to execute before later calls to + * executeCommand (e.g. mouseovers, which clean up after previous ones) then + * set getReply true to ensure that commands are not executed out of order. + * + * @param getReply + * @param msg + * @param cmds + * @return + */ + protected List executeCommand(boolean getReply, String msg, + StructureCommandI... cmds) + { + JalviewStructureDisplayI theViewer = getViewer(); + final long handle = msg == null ? 0 : theViewer.startProgressBar(msg); + if (getReply) { /* - * synchronous (same thread) execution so reply can be returned + * execute and wait for reply */ - final JalviewStructureDisplayI theViewer = getViewer(); - final long handle = msg == null ? 0 : theViewer.startProgressBar(msg); + List response = new ArrayList<>(); try { - return executeCommand(cmd, getReply); + for (StructureCommandI cmd : cmds) + { + List replies = executeCommand(cmd, true); + if (replies != null) + { + response.addAll(replies); + } + } + return response; } finally { if (msg != null) @@ -1076,81 +1152,39 @@ public abstract class AAStructureBindingModel } } } - else - { - /* - * asynchronous (new thread) execution if no reply needed - */ - final JalviewStructureDisplayI theViewer = getViewer(); - final long handle = msg == null ? 0 : theViewer.startProgressBar(msg); - SwingUtilities.invokeLater(new Runnable() + /* + * fire and forget + */ + String threadName = msg == null ? "StructureCommand" : msg; + new Thread(new Runnable() + { + @Override + public void run() { - @Override - public void run() + try { - try + for (StructureCommandI cmd : cmds) { executeCommand(cmd, false); - } finally + } + } finally + { + if (msg != null) { - if (msg != null) + SwingUtilities.invokeLater(new Runnable() { - theViewer.stopProgressBar(null, handle); - } + @Override + public void run() + { + theViewer.stopProgressBar(null, handle); + } + }); } } - }); - return null; - } - } - - /** - * Execute one structure viewer command. If {@code getReply} is true, may - * optionally return one or more reply messages, else returns null. - * - * @param cmd - * @param getReply - */ - protected abstract List executeCommand(StructureCommandI cmd, - boolean getReply); - - /** - * Executes one or more structure viewer commands. If a progress message is - * provided, it is shown first, and removed after all commands have been run. - * - * @param commands - * @param getReply - * @param msg - */ - protected List executeCommands(List commands, - boolean getReply, String msg) - { - /* - * show progress message if specified - */ - final JalviewStructureDisplayI theViewer = getViewer(); - final long handle = msg == null ? 0 : theViewer.startProgressBar(msg); - - List response = getReply ? new ArrayList<>() : null; - try - { - for (StructureCommandI cmd : commands) - { - List replies = executeCommand(cmd, getReply, null); - if (getReply && replies != null) - { - response.addAll(replies); - } } - return response; - } finally - { - if (msg != null) - { - theViewer.stopProgressBar(null, handle); - } - } + }, threadName).start(); + return null; } /** @@ -1168,7 +1202,7 @@ public abstract class AAStructureBindingModel List colourBySequenceCommands = commandGenerator .colourBySequence(colourMap); - executeCommands(colourBySequenceCommands, false, null); + executeCommands(colourBySequenceCommands, false, COLOURING_STRUCTURES); } /** @@ -1176,7 +1210,7 @@ public abstract class AAStructureBindingModel */ public void focusView() { - executeCommand(commandGenerator.focusView(), false, null); + executeCommand(false, null, commandGenerator.focusView()); } /** @@ -1224,8 +1258,7 @@ public abstract class AAStructureBindingModel } /** - * Returns the FeatureRenderer for the given alignment view, or null if - * feature display is turned off in the view. + * Returns the FeatureRenderer for the given alignment view * * @param avp * @return @@ -1238,9 +1271,7 @@ public abstract class AAStructureBindingModel { return null; } - return ap.getAlignViewport().isShowSequenceFeatures() - ? ap.getFeatureRenderer() - : null; + return ap.getFeatureRenderer(); } protected void setStructureCommands(StructureCommandsI cmd) @@ -1275,6 +1306,12 @@ public abstract class AAStructureBindingModel @Override public void updateColours(Object source) { + if (getViewer() == null) + { + // can happen if a viewer was not instantiated or cleaned up and is still + // registered - mostly during tests + return; + } AlignmentViewPanel ap = (AlignmentViewPanel) source; // ignore events from panels not used to colour this view if (!getViewer().isUsedForColourBy(ap)) @@ -1295,40 +1332,6 @@ public abstract class AAStructureBindingModel protected abstract ViewerType getViewerType(); /** - * Send a structure viewer command asynchronously in a new thread. If the - * progress message is not null, display this message while the command is - * executing. - * - * @param command - * @param progressMsg - */ - protected void sendAsynchronousCommand(StructureCommandI command, - String progressMsg) - { - final JalviewStructureDisplayI theViewer = getViewer(); - final long handle = progressMsg == null ? 0 - : theViewer.startProgressBar(progressMsg); - SwingUtilities.invokeLater(new Runnable() - { - @Override - public void run() - { - try - { - executeCommand(command, false, null); - } finally - { - if (progressMsg != null) - { - theViewer.stopProgressBar(null, handle); - } - } - } - }); - - } - - /** * Builds a data structure which records mapped structure residues for each * colour. From this we can easily generate the viewer commands for colour by * sequence. Constructs and returns a map of {@code Color} to @@ -1536,7 +1539,7 @@ public abstract class AAStructureBindingModel saveSession(f); } catch (IOException e) { - Cache.log.error(String.format("Error saving %s session: %s", prefix, + Console.error(String.format("Error saving %s session: %s", prefix, e.toString())); }