From: gmungoc Date: Wed, 12 Nov 2014 16:55:00 +0000 (+0000) Subject: JAL-1528 bug fixes and adjustments to Chimera interface X-Git-Tag: Release_2_8_2b1^2~33^2~3 X-Git-Url: http://source.jalview.org/gitweb/?a=commitdiff_plain;h=d3a2fdc864b586b5c604335dd715ec215b679197;p=jalview.git JAL-1528 bug fixes and adjustments to Chimera interface --- diff --git a/resources/lang/Messages.properties b/resources/lang/Messages.properties index a2db06d..72801dd 100644 --- a/resources/lang/Messages.properties +++ b/resources/lang/Messages.properties @@ -485,6 +485,10 @@ label.edit_sequence = Edit Sequence label.edit_sequences = Edit Sequences label.sequence_details = Sequence Details label.jmol_help = Jmol Help +label.chimera_help = Chimera Help +label.close_viewer = Close Viewer +label.confirm_close_chimera = Do you want to close the Chimera window? +label.chimera_help = Chimera Help label.all = All label.sort_by = Sort alignment by label.sort_by_score = Sort by Score @@ -512,7 +516,7 @@ label.toggle_absolute_relative_display_threshold = Toggle between absolute and r label.display_features_same_type_different_label_using_different_colour = Display features of the same type with a different label using a different colour. (e.g. domain features) label.select_colour_minimum_value = Select Colour for Minimum Value label.select_colour_maximum_value = Select Colour for Maximum Value -label.open_new_jmol_view_with_all_structures_associated_current_selection_superimpose_using_alignment = Open a new Jmol view with all structures associated with the current selection and superimpose them using the alignment. +label.open_new_jmol_view_with_all_structures_associated_current_selection_superimpose_using_alignment = Open a new structure viewer with all structures associated with the current selection and superimpose them using the alignment. label.open_url_param = Open URL {0} label.open_url_seqs_param = Open URL ({0}..) ({1} seqs) label.load_pdb_file_associate_with_sequence = Load a PDB file and associate it with sequence {0} @@ -601,6 +605,7 @@ label.das_settings = DAS Settings label.web_services = Web Services 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.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
when a web service URL cannot be accessed by Jalview
when it starts up @@ -649,7 +654,7 @@ label.edit_name_and_description_current_group = Edit name and description of cur label.view_structure_for = View structure for {0} label.view_all_structures = View all {0} structures. label.view_all_representative_structures = View all {0} representative structures. -label.open_new_jmol_view_with_all_representative_structures_associated_current_selection_superimpose_using_alignment = Opens a new Jmol view with all representative structures\nassociated with the current selection\nsuperimposed with the current alignment. +label.open_new_jmol_view_with_all_representative_structures_associated_current_selection_superimpose_using_alignment = Opens a new structure viewer with all representative structures\nassociated with the current selection\nsuperimposed with the current alignment. label.associate_structure_with_sequence = Associate Structure with Sequence label.from_file = from file label.enter_pdb_id = Enter PDB Id @@ -695,8 +700,10 @@ label.jalview_pca_calculation = Jalview PCA Calculation label.link_name = Link Name label.pdb_file = PDB file label.colour_with_jmol = Colour with Jmol +label.colour_with_chimera = Colour with Chimera label.align_structures = Align structures label.jmol = Jmol +label.chimera = Chimera label.sort_alignment_by_tree = Sort Alignment By Tree label.mark_unlinked_leaves = Mark Unlinked Leaves label.associate_leaves_with = Associate Leaves With @@ -836,7 +843,7 @@ label.service_url = Service URL label.copied_sequences = Copied sequences label.cut_sequences = Cut Sequences label.conservation_colour_increment = Conservation Colour Increment ({0}) -label.percentage_identity_thereshold = Percentage Identity Thereshold ({0}) +label.percentage_identity_thereshold = Percentage Identity Threshold ({0}) label.error_unsupported_owwner_user_colour_scheme = Unsupported owner for User Colour scheme dialog label.save_alignment_to_file = Save Alignment to file label.save_features_to_file = Save Features to File @@ -1141,7 +1148,7 @@ label.edit_jabaws_url = Edit JABAWS URL label.add_jabaws_url = Add new JABAWS URL label.news_from_jalview = News from http://www.jalview.org label.cut_paste_alignmen_file = Cut & Paste Alignment File -label.enter_redundancy_thereshold = Enter the redundancy thereshold +label.enter_redundancy_thereshold = Enter the redundancy threshold label.select_dark_light_set_thereshold = Select a dark and light text colour, then set the threshold to
switch between colours, based on background colour
label.select_feature_colour = Select Feature Colour label.delete_all = Delete all sequences diff --git a/src/ext/edu/ucsf/rbvi/strucviz2/ChimeraManager.java b/src/ext/edu/ucsf/rbvi/strucviz2/ChimeraManager.java index c0b3a39..a7440e7 100644 --- a/src/ext/edu/ucsf/rbvi/strucviz2/ChimeraManager.java +++ b/src/ext/edu/ucsf/rbvi/strucviz2/ChimeraManager.java @@ -152,6 +152,20 @@ public class ChimeraManager public List openModel(String modelPath, ModelType type) { + return openModel(modelPath, getFileNameFromPath(modelPath), type); + } + + /** + * Overloaded method to allow Jalview to pass in a model name. + * + * @param modelPath + * @param modelName + * @param type + * @return + */ + public List openModel(String modelPath, String modelName, + ModelType type) + { logger.info("chimera open " + modelPath); stopListening(); List response = null; @@ -190,22 +204,14 @@ public class ChimeraManager { continue; } - String modelName = modelPath; - // TODO: [Optional] Convert path to name in a better way - if (modelPath.lastIndexOf(File.separator) > 0) - { - modelName = modelPath.substring(modelPath - .lastIndexOf(File.separator) + 1); - } - else if (modelPath.lastIndexOf("/") > 0) - { - modelName = modelPath - .substring(modelPath.lastIndexOf("/") + 1); - } ChimeraModel newModel = new ChimeraModel(modelName, type, modelNumbers[0], modelNumbers[1]); currentModelsMap.put(modelNumber, newModel); models.add(newModel); + // patch for Jalview - set model name in Chimera + sendChimeraCommand("setattr M name " + modelName + " #" + + modelNumbers[0], false); + // end patch for Jalview modelNumbers = null; } } @@ -265,6 +271,34 @@ public class ChimeraManager return models; } + /** + * Refactored method to extract the last (or only) element delimited by file + * path separator. + * + * @param modelPath + * @return + */ + private String getFileNameFromPath(String modelPath) + { + String modelName = modelPath; + if (modelPath == null) + { + return null; + } + // TODO: [Optional] Convert path to name in a better way + if (modelPath.lastIndexOf(File.separator) > 0) + { + modelName = modelPath.substring(modelPath + .lastIndexOf(File.separator) + 1); + } + else if (modelPath.lastIndexOf("/") > 0) + { + modelName = modelPath + .substring(modelPath.lastIndexOf("/") + 1); + } + return modelName; + } + public void closeModel(ChimeraModel model) { // int model = structure.modelNumber(); @@ -450,14 +484,20 @@ public class ChimeraManager public boolean isChimeraLaunched() { - // TODO: [Optional] What is the best way to test if chimera is launched? - - // sendChimeraCommand("test", true) !=null + boolean launched = false; if (chimera != null) { - return true; + try + { + chimera.exitValue(); + // if we get here, process has ended + } catch (IllegalThreadStateException e) + { + // ok - not yet terminated + launched = true; + } } - return false; + return launched; } public boolean launchChimera(List chimeraPaths) @@ -533,7 +573,7 @@ public class ChimeraManager { return null; } - return ChimUtils.parseModelColor((String) colorLines.get(0)); + return ChimUtils.parseModelColor(colorLines.get(0)); } /** @@ -647,6 +687,7 @@ public class ChimeraManager { return null; } + // TODO do we need a maximum wait time before aborting? while (busy) { try @@ -658,32 +699,38 @@ public class ChimeraManager ; } busy = true; - chimeraListenerThreads.clearResponse(command); - String text = command.concat("\n"); - // System.out.println("send command to chimera: " + text); try { - // send the command - chimera.getOutputStream().write(text.getBytes()); - chimera.getOutputStream().flush(); - } catch (IOException e) - { - // logger.info("Unable to execute command: " + text); - // logger.info("Exiting..."); - logger.warn("Unable to execute command: " + text); - logger.warn("Exiting..."); - clearOnChimeraExit(); - busy = false; - return null; - } - if (!reply) + chimeraListenerThreads.clearResponse(command); + String text = command.concat("\n"); + // System.out.println("send command to chimera: " + text); + try + { + // send the command + chimera.getOutputStream().write(text.getBytes()); + chimera.getOutputStream().flush(); + } catch (IOException e) + { + // logger.info("Unable to execute command: " + text); + // logger.info("Exiting..."); + logger.warn("Unable to execute command: " + text); + logger.warn("Exiting..."); + clearOnChimeraExit(); + // busy = false; + return null; + } + if (!reply) + { + // busy = false; + return null; + } + List rsp = chimeraListenerThreads.getResponse(command); + // busy = false; + return rsp; + } finally { busy = false; - return null; } - List rsp = chimeraListenerThreads.getResponse(command); - busy = false; - return rsp; } public StructureManager getStructureManager() diff --git a/src/ext/edu/ucsf/rbvi/strucviz2/port/ListenerThreads.java b/src/ext/edu/ucsf/rbvi/strucviz2/port/ListenerThreads.java index dee027b..883d536 100644 --- a/src/ext/edu/ucsf/rbvi/strucviz2/port/ListenerThreads.java +++ b/src/ext/edu/ucsf/rbvi/strucviz2/port/ListenerThreads.java @@ -12,7 +12,7 @@ import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import ext.edu.ucsf.rbvi.strucviz2.*; +import ext.edu.ucsf.rbvi.strucviz2.StructureManager; /*************************************************** * Thread Classes * @@ -67,6 +67,7 @@ public class ListenerThreads extends Thread { public List getResponse(String command) { List reply; // System.out.println("getResponse: "+command); + // TODO do we need a maximum wait time before aborting? while (!replyLog.containsKey(command)) { try { Thread.currentThread().sleep(100); @@ -88,7 +89,9 @@ public class ListenerThreads extends Thread { } catch (InterruptedException e) { } if (replyLog.containsKey(command)) - replyLog.remove(command); + { + replyLog.remove(command); + } return; } @@ -99,7 +102,9 @@ public class ListenerThreads extends Thread { */ private void chimeraRead() throws IOException { if (chimera == null) - return; + { + return; + } String line = null; while ((line = lineReader.readLine()) != null) { @@ -153,9 +158,13 @@ public class ListenerThreads extends Thread { replyLog.put(command, reply); } if (updateModels) - (new ModelUpdater()).start(); + { + (new ModelUpdater()).start(); + } if (updateSelection) - (new SelectionUpdater()).start(); + { + (new SelectionUpdater()).start(); + } if (importNetwork) { (new NetworkUpdater(line)).start(); } diff --git a/src/jalview/ext/rbvi/chimera/JalviewChimeraBinding.java b/src/jalview/ext/rbvi/chimera/JalviewChimeraBinding.java index a39f355..3f2d5e4 100644 --- a/src/jalview/ext/rbvi/chimera/JalviewChimeraBinding.java +++ b/src/jalview/ext/rbvi/chimera/JalviewChimeraBinding.java @@ -44,10 +44,9 @@ import java.io.File; import java.util.ArrayList; import java.util.Enumeration; import java.util.HashMap; -import java.util.Hashtable; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import java.util.Vector; import ext.edu.ucsf.rbvi.strucviz2.ChimeraManager; import ext.edu.ucsf.rbvi.strucviz2.ChimeraModel; @@ -59,6 +58,10 @@ public abstract class JalviewChimeraBinding extends SequenceStructureBinding, StructureSelectionManagerProvider { + private static final String PHOSPHORUS = "P"; + + private static final String ALPHACARBON = "CA"; + private StructureManager csm; private ChimeraManager viewer; @@ -95,18 +98,18 @@ public abstract class JalviewChimeraBinding extends /** * when true, try to search the associated datamodel for sequences that are - * associated with any unknown structures in the Jmol view. + * associated with any unknown structures in the Chimera view. */ private boolean associateNewStructs = false; - Vector atomsPicked = new Vector(); + List atomsPicked = new ArrayList(); - public Vector chainNames; + public List chainNames; - Hashtable chainFile; + private Map chainFile; /** - * array of target chains for seuqences - tied to pdbentry and sequence[] + * array of target chains for sequences - tied to pdbentry and sequence[] */ protected String[][] chains; @@ -116,7 +119,7 @@ public abstract class JalviewChimeraBinding extends public String fileLoadingError; - private Map> chimmaps = new HashMap>(); + private Map> chimmaps = new LinkedHashMap>(); private List mdlToFile = new ArrayList(); @@ -138,7 +141,7 @@ public abstract class JalviewChimeraBinding extends try { List oldList = viewer.getModelList(); - viewer.openModel(file, ModelType.PDB_MODEL); + viewer.openModel(file, pe.getId(), ModelType.PDB_MODEL); List newList = viewer.getModelList(); if (oldList.size() < newList.size()) { @@ -288,31 +291,32 @@ public abstract class JalviewChimeraBinding extends * prepare the view for a given set of models/chains. chainList contains * strings of the form 'pdbfilename:Chaincode' * - * @param chainList + * @param toshow * list of chains to make visible */ - public void centerViewer(Vector chainList) + public void centerViewer(List toshow) { - StringBuffer cmd = new StringBuffer(); - String lbl; + StringBuilder cmd = new StringBuilder(64); int mlength, p; - for (int i = 0, iSize = chainList.size(); i < iSize; i++) + for (String lbl : toshow) { mlength = 0; - lbl = (String) chainList.elementAt(i); do { p = mlength; mlength = lbl.indexOf(":", p); } while (p < mlength && mlength < (lbl.length() - 2)); // TODO: lookup each pdb id and recover proper model number for it. - cmd.append("#" + getModelNum((String) chainFile.get(lbl)) + "." + cmd.append("#" + getModelNum(chainFile.get(lbl)) + "." + lbl.substring(mlength + 1) + " or "); } if (cmd.length() > 0) + { cmd.setLength(cmd.length() - 4); - evalStateCommand("~display #*; ~ribbon #*; ribbon " + cmd + ";focus " - + cmd,false); + } + String cmdstring = cmd.toString(); + evalStateCommand("~display #*; ~ribbon #*; ribbon " + cmdstring + + ";focus " + cmdstring, false); } public void closeViewer() @@ -394,7 +398,7 @@ public abstract class JalviewChimeraBinding extends int[] _refStructure, ColumnSelection[] _hiddenCols) { assert (_alignment.length == _refStructure.length && _alignment.length != _hiddenCols.length); - StringBuffer allComs = new StringBuffer(); // whole shebang for superposition + StringBuilder allComs = new StringBuilder(128); // Chimera superposition cmd String[] files = getPdbFile(); // check to see if we are still waiting for Jmol files long starttime = System.currentTimeMillis(); @@ -427,7 +431,7 @@ public abstract class JalviewChimeraBinding extends if (waiting) { System.err - .println("RUNTIME PROBLEM: Jmol seems to be taking a long time to process all the structures."); + .println("RUNTIME PROBLEM: Chimera seems to be taking a long time to process all the structures."); return; } refreshPdbEntries(); @@ -455,7 +459,6 @@ public abstract class JalviewChimeraBinding extends { refStructure = -1; } - StringBuffer command = new StringBuffer(); boolean matched[] = new boolean[alignment.getWidth()]; for (int m = 0; m < matched.length; m++) @@ -466,10 +469,9 @@ public abstract class JalviewChimeraBinding extends 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]; - String[] atomS = new String[files.length]; + String[] atomSpec = new String[files.length]; for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++) { StructureMapping[] mapping = ssm.getMapping(files[pdbfnum]); @@ -536,7 +538,7 @@ public abstract class JalviewChimeraBinding extends } chainNames[pdbfnum] = mapping[m].getPdbId() + targetC[pdbfnum]; - atomS[pdbfnum] = asp.getRNA()!=null ? "P" : "CA"; + atomSpec[pdbfnum] = asp.getRNA() != null ? PHOSPHORUS : ALPHACARBON; // move on to next pdb file s = sequence[pdbfnum].length; break; @@ -619,6 +621,7 @@ public abstract class JalviewChimeraBinding extends } } } + StringBuilder command = new StringBuilder(256); for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++) { if (pdbfnum == refStructure || selcom[pdbfnum] == null @@ -626,23 +629,31 @@ public abstract class JalviewChimeraBinding extends { continue; } - if (command.length()>0) + if (command.length() > 0) { command.append(";"); } - command.append("match"); - // form the matched pair strings - for (int s = 0; s < 2; s++) - { - command.append(" #"+(s == 0 ? pdbfnum : refStructure)+".1"); - // note - need to select on first model, otherwise it all goes wrong! - command.append(selcom[(s == 0 ? pdbfnum : refStructure)]); - command.append("@"+atomS[(s == 0 ? pdbfnum : refStructure)]); // match on backbone alpha/polyphosphate - } + /* + * Form Chimera match command, from the 'new' structure to the + * 'reference' structure e.g. (residues 1-91, chain B/A, alphacarbons): + * + * match #1:1-91.B@CA #0:1-91.A@CA + * + * @see + * https://www.cgl.ucsf.edu/chimera/docs/UsersGuide/midas/match.html + */ + command.append("match #" + pdbfnum /* +".1" */); + // TODO: handle sub-models + command.append(selcom[pdbfnum]); + command.append("@" + atomSpec[pdbfnum]); + command.append(" #" + refStructure /* +".1" */); + command.append(selcom[refStructure]); + command.append("@" + atomSpec[refStructure]); } if (selectioncom.length() > 0) { + // TODO remove debug output System.out.println("Select regions:\n" + selectioncom.toString()); System.out .println("Superimpose command(s):\n" + command.toString()); @@ -661,7 +672,7 @@ public abstract class JalviewChimeraBinding extends allComs.append("; ~display all; chain @CA|P; ribbon " + selectioncom.toString() + ""); // evalStateCommand("select *; backbone; select "+selcom.toString()+"; cartoons; center "+selcom.toString()); - evalStateCommand(allComs.toString(),false); + evalStateCommand(allComs.toString(), true /* false */); } } @@ -689,8 +700,9 @@ public abstract class JalviewChimeraBinding extends // @Override // public void run() // { - lastReply = viewer.sendChimeraCommand(command, resp); - if (debug) + // trim command or it may never find a match in the replyLog!! + lastReply = viewer.sendChimeraCommand(command.trim(), resp); + if (debug && resp) { log("Response from command ('" + command + "') was:\n" + lastReply); @@ -719,7 +731,9 @@ public abstract class JalviewChimeraBinding extends jalview.api.AlignmentViewPanel alignmentv) { if (!colourBySequence || !loadingFinished) + { return; + } if (ssm == null) { return; @@ -738,12 +752,14 @@ public abstract class JalviewChimeraBinding extends for (jalview.structure.StructureMappingcommandSet cpdbbyseq : ChimeraCommands .getColourBySequenceCommand(ssm, files, sequence, sr, fr, alignment)) + { for (String cbyseq : cpdbbyseq.commands) { waitForChimera(); evalStateCommand(cbyseq, false); waitForChimera(); } + } } private void waitForChimera() @@ -767,25 +783,6 @@ public abstract class JalviewChimeraBinding extends this.colourBySequence = colourBySequence; } - public void createImage(String file, String type, int quality) - { - System.out.println("JMOL CREATE IMAGE"); - } - - public String createImage(String fileName, String type, - Object textOrBytes, int quality) - { - System.out.println("JMOL CREATE IMAGE"); - return null; - } - - public String eval(String strEval) - { - // System.out.println(strEval); - // "# 'eval' is implemented only for the applet."; - return null; - } - // End StructureListener // ////////////////////////// @@ -804,7 +801,9 @@ public abstract class JalviewChimeraBinding extends String pdbfile) { if (getModelNum(pdbfile) < 0) + { return null; + } log("get model / residue colour attribute unimplemented"); return null; } @@ -837,7 +836,9 @@ public abstract class JalviewChimeraBinding extends for (int i = 0; i < mfn.length; i++) { if (mfn[i].equalsIgnoreCase(modelFileName)) + { return i; + } } return -1; } @@ -996,8 +997,10 @@ public abstract class JalviewChimeraBinding extends String chainId; if (strInfo.indexOf(":") > -1) + { chainId = strInfo.substring(strInfo.indexOf(":") + 1, strInfo.indexOf(".")); + } else { chainId = " "; @@ -1035,7 +1038,9 @@ public abstract class JalviewChimeraBinding extends ; } if (lastMessage == null || !lastMessage.equals(strInfo)) + { ssm.mouseOverStructure(pdbResNum, chainId, pdbfilename); + } lastMessage = strInfo; } @@ -1054,13 +1059,17 @@ public abstract class JalviewChimeraBinding extends int chainSeparator = strInfo.indexOf(":"); int p = 0; if (chainSeparator == -1) + { chainSeparator = strInfo.indexOf("."); + } String picked = strInfo.substring(strInfo.indexOf("]") + 1, chainSeparator); String mdlString = ""; if ((p = strInfo.indexOf(":")) > -1) + { picked += strInfo.substring(p + 1, strInfo.indexOf(".")); + } if ((p = strInfo.indexOf("/")) > -1) { @@ -1073,12 +1082,12 @@ public abstract class JalviewChimeraBinding extends if (!atomsPicked.contains(picked)) { viewer.select(picked); - atomsPicked.addElement(picked); + atomsPicked.add(picked); } else { viewer.select("not " + picked); - atomsPicked.removeElement(picked); + atomsPicked.remove(picked); } viewerCommandHistory(true); // TODO: in application this happens @@ -1093,7 +1102,7 @@ public abstract class JalviewChimeraBinding extends // incremented every time a load notification is successfully handled - // lightweight mechanism for other threads to detect when they can start - // referrring to new structures. + // referring to new structures. private long loadNotifiesHandled = 0; public long getLoadNotifiesHandled() @@ -1119,8 +1128,8 @@ public abstract class JalviewChimeraBinding extends fileLoadingError = null; String[] oldmodels = modelFileNames; modelFileNames = null; - chainNames = new Vector(); - chainFile = new Hashtable(); + chainNames = new ArrayList(); + chainFile = new HashMap(); boolean notifyLoaded = false; String[] modelfilenames = getPdbFile(); // first check if we've lost any structures @@ -1181,7 +1190,9 @@ public abstract class JalviewChimeraBinding extends colourBySequence = false; if (cs == null) + { return; + } String res; int index; @@ -1195,7 +1206,9 @@ public abstract class JalviewChimeraBinding extends res = en.nextElement().toString(); index = ((Integer) ResidueProperties.aa3Hash.get(res)).intValue(); if (index > 20) + { continue; + } col = cs.findColour(ResidueProperties.aa[index].charAt(0)); // TODO: need colour string function and res selection here @@ -1289,21 +1302,20 @@ public abstract class JalviewChimeraBinding extends public synchronized PDBEntry[] addSequenceAndChain(PDBEntry[] pdbe, SequenceI[][] seq, String[][] chns) { - int pe = -1; - Vector v = new Vector(); - Vector rtn = new Vector(); + List v = new ArrayList(); + List rtn = new ArrayList(); for (int i = 0; i < pdbentry.length; i++) { - v.addElement(pdbentry[i]); + v.add(pdbentry[i]); } for (int i = 0; i < pdbe.length; i++) { int r = v.indexOf(pdbe[i]); if (r == -1 || r >= pdbentry.length) { - rtn.addElement(new int[] + rtn.add(new int[] { v.size(), i }); - v.addElement(pdbe[i]); + v.add(pdbe[i]); } else { @@ -1311,12 +1323,11 @@ public abstract class JalviewChimeraBinding extends addSequenceAndChain(r, seq[i], chns[i]); } } - pdbe = new PDBEntry[v.size()]; - v.copyInto(pdbe); + pdbe = v.toArray(new PDBEntry[v.size()]); pdbentry = pdbe; if (rtn.size() > 0) { - // expand the tied seuqence[] and string[] arrays + // expand the tied sequence[] and string[] arrays SequenceI[][] sqs = new SequenceI[pdbentry.length][]; String[][] sch = new String[pdbentry.length][]; System.arraycopy(sequence, 0, sqs, 0, sequence.length); @@ -1326,7 +1337,7 @@ public abstract class JalviewChimeraBinding extends pdbe = new PDBEntry[rtn.size()]; for (int r = 0; r < pdbe.length; r++) { - int[] stri = ((int[]) rtn.elementAt(r)); + int[] stri = (rtn.get(r)); // record the pdb file as a new addition pdbe[r] = pdbentry[stri[0]]; // and add the new sequence/chain entries @@ -1340,9 +1351,14 @@ public abstract class JalviewChimeraBinding extends return pdbe; } + /** + * Adds sequences to the pe'th pdbentry's sequence set. + * + * @param pe + * @param seq + */ public void addSequence(int pe, SequenceI[] seq) { - // add sequences to the pe'th pdbentry's seuqence set. addSequenceAndChain(pe, seq, null); } @@ -1350,11 +1366,14 @@ public abstract class JalviewChimeraBinding extends { if (pe < 0 || pe >= pdbentry.length) { - throw new Error(MessageManager.formatMessage("error.implementation_error_no_pdbentry_from_index", new String[]{Integer.valueOf(pe).toString()})); + throw new Error(MessageManager.formatMessage( + "error.implementation_error_no_pdbentry_from_index", + new Object[] + { Integer.valueOf(pe).toString() })); } final String nullChain = "TheNullChain"; - Vector s = new Vector(); - Vector c = new Vector(); + List s = new ArrayList(); + List c = new ArrayList(); if (chains == null) { chains = new String[pdbentry.length][]; @@ -1363,23 +1382,23 @@ public abstract class JalviewChimeraBinding extends { for (int i = 0; i < sequence[pe].length; i++) { - s.addElement(sequence[pe][i]); + s.add(sequence[pe][i]); if (chains[pe] != null) { if (i < chains[pe].length) { - c.addElement(chains[pe][i]); + c.add(chains[pe][i]); } else { - c.addElement(nullChain); + c.add(nullChain); } } else { if (tchain != null && tchain.length > 0) { - c.addElement(nullChain); + c.add(nullChain); } } } @@ -1388,20 +1407,18 @@ public abstract class JalviewChimeraBinding extends { if (!s.contains(seq[i])) { - s.addElement(seq[i]); + s.add(seq[i]); if (tchain != null && i < tchain.length) { - c.addElement(tchain[i] == null ? nullChain : tchain[i]); + c.add(tchain[i] == null ? nullChain : tchain[i]); } } } - SequenceI[] tmp = new SequenceI[s.size()]; - s.copyInto(tmp); + SequenceI[] tmp = s.toArray(new SequenceI[s.size()]); sequence[pe] = tmp; if (c.size() > 0) { - String[] tch = new String[c.size()]; - c.copyInto(tch); + String[] tch = c.toArray(new String[c.size()]); for (int i = 0; i < tch.length; i++) { if (tch[i] == nullChain) diff --git a/src/jalview/gui/AppJmol.java b/src/jalview/gui/AppJmol.java index 5d4b910..fcb31eb 100644 --- a/src/jalview/gui/AppJmol.java +++ b/src/jalview/gui/AppJmol.java @@ -176,14 +176,14 @@ public class AppJmol extends GStructureViewer implements Runnable, { jmb.setColourBySequence(false); seqColour.setSelected(false); - jmolColour.setSelected(true); + viewerColour.setSelected(true); } if (usetoColour) { useAlignmentPanelForColourbyseq(ap); jmb.setColourBySequence(true); seqColour.setSelected(true); - jmolColour.setSelected(false); + viewerColour.setSelected(false); } this.setBounds(bounds); initMenus(); @@ -205,7 +205,7 @@ public class AppJmol extends GStructureViewer implements Runnable, private void initMenus() { seqColour.setSelected(jmb.isColourBySequence()); - jmolColour.setSelected(!jmb.isColourBySequence()); + viewerColour.setSelected(!jmb.isColourBySequence()); if (_colourwith == null) { _colourwith = new Vector(); @@ -251,8 +251,8 @@ public class AppJmol extends GStructureViewer implements Runnable, } }); handler.itemStateChanged(null); - jmolActionMenu.add(alpanels); - jmolActionMenu.addMenuListener(new MenuListener() + viewerActionMenu.add(alpanels); + viewerActionMenu.addMenuListener(new MenuListener() { @Override @@ -303,8 +303,13 @@ public class AppJmol extends GStructureViewer implements Runnable, "label.pdb_entry_is_already_displayed", new String[] { pdbentry.getId() }), MessageManager.formatMessage( "label.map_sequences_to_visible_window", new String[] - { pdbentry.getId() }), JOptionPane.YES_NO_OPTION); + { pdbentry.getId() }), + JOptionPane.YES_NO_CANCEL_OPTION); + if (option == JOptionPane.CANCEL_OPTION) + { + return; + } if (option == JOptionPane.YES_OPTION) { // TODO : Fix multiple seq to one chain issue here. @@ -366,7 +371,11 @@ public class AppJmol extends GStructureViewer implements Runnable, { pdbentry.getId(), topJmol.getTitle() }), MessageManager .getString("label.align_to_existing_structure_view"), - JOptionPane.YES_NO_OPTION); + JOptionPane.YES_NO_CANCEL_OPTION); + if (option == JOptionPane.CANCEL_OPTION) + { + return; + } if (option == JOptionPane.YES_OPTION) { topJmol.useAlignmentPanelForSuperposition(ap); @@ -533,7 +542,7 @@ public class AppJmol extends GStructureViewer implements Runnable, useAlignmentPanelForColourbyseq(nap); jmb.setColourBySequence(enableColourBySeq); seqColour.setSelected(enableColourBySeq); - jmolColour.setSelected(!enableColourBySeq); + viewerColour.setSelected(!enableColourBySeq); } public void useAlignmentPanelForColourbyseq(AlignmentPanel nap) @@ -614,25 +623,22 @@ public class AppJmol extends GStructureViewer implements Runnable, return; } - private Vector getJmolsFor(AlignmentPanel ap2) + private Vector getJmolsFor(AlignmentPanel apanel) { - Vector otherJmols = new Vector(); - // Now this AppJmol is mapped to new sequences. We must add them to - // the exisiting array + Vector result = new Vector(); JInternalFrame[] frames = Desktop.instance.getAllFrames(); - for (int i = 0; i < frames.length; i++) + for (JInternalFrame frame : frames) { - if (frames[i] instanceof AppJmol) + if (frame instanceof AppJmol) { - AppJmol topJmol = ((AppJmol) frames[i]); - if (topJmol.isLinkedWith(ap2)) + if (((AppJmol) frame).isLinkedWith(apanel)) { - otherJmols.addElement(topJmol); + result.addElement(frame); } } } - return otherJmols; + return result; } void initJmol(String command) @@ -927,6 +933,7 @@ public class AppJmol extends GStructureViewer implements Runnable, worker = null; } + @Override public void pdbFile_actionPerformed(ActionEvent actionEvent) { JalviewFileChooser chooser = new JalviewFileChooser( @@ -964,6 +971,7 @@ public class AppJmol extends GStructureViewer implements Runnable, } } + @Override public void viewMapping_actionPerformed(ActionEvent actionEvent) { jalview.gui.CutAndPasteTransfer cap = new jalview.gui.CutAndPasteTransfer(); @@ -987,23 +995,13 @@ public class AppJmol extends GStructureViewer implements Runnable, 600); } - /** - * DOCUMENT ME! - * - * @param e - * DOCUMENT ME! - */ + @Override public void eps_actionPerformed(ActionEvent e) { makePDBImage(jalview.util.ImageMaker.TYPE.EPS); } - /** - * DOCUMENT ME! - * - * @param e - * DOCUMENT ME! - */ + @Override public void png_actionPerformed(ActionEvent e) { makePDBImage(jalview.util.ImageMaker.TYPE.PNG); @@ -1045,15 +1043,17 @@ public class AppJmol extends GStructureViewer implements Runnable, } } - public void jmolColour_actionPerformed(ActionEvent actionEvent) + @Override + public void viewerColour_actionPerformed(ActionEvent actionEvent) { - if (jmolColour.isSelected()) + if (viewerColour.isSelected()) { // disable automatic sequence colouring. jmb.setColourBySequence(false); } } + @Override public void seqColour_actionPerformed(ActionEvent actionEvent) { jmb.setColourBySequence(seqColour.isSelected()); @@ -1079,71 +1079,83 @@ public class AppJmol extends GStructureViewer implements Runnable, } } + @Override public void chainColour_actionPerformed(ActionEvent actionEvent) { chainColour.setSelected(true); jmb.colourByChain(); } + @Override public void chargeColour_actionPerformed(ActionEvent actionEvent) { chargeColour.setSelected(true); jmb.colourByCharge(); } + @Override public void zappoColour_actionPerformed(ActionEvent actionEvent) { zappoColour.setSelected(true); jmb.setJalviewColourScheme(new ZappoColourScheme()); } + @Override public void taylorColour_actionPerformed(ActionEvent actionEvent) { taylorColour.setSelected(true); jmb.setJalviewColourScheme(new TaylorColourScheme()); } + @Override public void hydroColour_actionPerformed(ActionEvent actionEvent) { hydroColour.setSelected(true); jmb.setJalviewColourScheme(new HydrophobicColourScheme()); } + @Override public void helixColour_actionPerformed(ActionEvent actionEvent) { helixColour.setSelected(true); jmb.setJalviewColourScheme(new HelixColourScheme()); } + @Override public void strandColour_actionPerformed(ActionEvent actionEvent) { strandColour.setSelected(true); jmb.setJalviewColourScheme(new StrandColourScheme()); } + @Override public void turnColour_actionPerformed(ActionEvent actionEvent) { turnColour.setSelected(true); jmb.setJalviewColourScheme(new TurnColourScheme()); } + @Override public void buriedColour_actionPerformed(ActionEvent actionEvent) { buriedColour.setSelected(true); jmb.setJalviewColourScheme(new BuriedColourScheme()); } + @Override public void purinePyrimidineColour_actionPerformed(ActionEvent actionEvent) { setJalviewColourScheme(new PurinePyrimidineColourScheme()); } + @Override public void userColour_actionPerformed(ActionEvent actionEvent) { userColour.setSelected(true); new UserDefinedColours(this, null); } + @Override public void backGround_actionPerformed(ActionEvent actionEvent) { java.awt.Color col = JColorChooser.showDialog(this, @@ -1154,7 +1166,8 @@ public class AppJmol extends GStructureViewer implements Runnable, } } - public void jmolHelp_actionPerformed(ActionEvent actionEvent) + @Override + public void showHelp_actionPerformed(ActionEvent actionEvent) { try { @@ -1274,7 +1287,7 @@ public class AppJmol extends GStructureViewer implements Runnable, this.setTitle(jmb.getViewerTitle()); if (jmb.getPdbFile().length > 1 && jmb.sequence.length > 1) { - jmolActionMenu.setVisible(true); + viewerActionMenu.setVisible(true); } if (!jmb.isLoadingFromArchive()) { @@ -1293,11 +1306,11 @@ public class AppJmol extends GStructureViewer implements Runnable, _alignwith.add(ap); } ; - for (Component c : jmolActionMenu.getMenuComponents()) + for (Component c : viewerActionMenu.getMenuComponents()) { if (c != alignStructs) { - jmolActionMenu.remove((JMenuItem) c); + viewerActionMenu.remove((JMenuItem) c); } } final ItemListener handler; diff --git a/src/jalview/gui/ChimeraViewFrame.java b/src/jalview/gui/ChimeraViewFrame.java index 236d094..6278536 100644 --- a/src/jalview/gui/ChimeraViewFrame.java +++ b/src/jalview/gui/ChimeraViewFrame.java @@ -44,6 +44,7 @@ import jalview.schemes.TurnColourScheme; import jalview.schemes.ZappoColourScheme; import jalview.util.MessageManager; import jalview.util.Platform; +import jalview.ws.dbsources.Pdb; import java.awt.Component; import java.awt.event.ActionEvent; @@ -54,9 +55,9 @@ import java.io.BufferedReader; import java.io.File; import java.io.FileOutputStream; import java.io.FileReader; +import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; -import java.util.Enumeration; import java.util.List; import java.util.Vector; @@ -81,70 +82,59 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable, ViewSetProvider, JalviewStructureDisplayI { - JalviewChimeraBindingModel jmb; + private JalviewChimeraBindingModel jmb; + + /* + * list of sequenceSet ids associated with the view + */ + private ArrayList _aps = new ArrayList(); + + /* + * list of alignment panels to use for superposition + */ + private Vector _alignwith = new Vector(); + + /* + * list of alignment panels that are used for colouring structures by aligned + * sequences + */ + private Vector _colourwith = new Vector(); + + private boolean allChainsSelected = false; + + private boolean alignAddedStructures = false; AlignmentPanel ap; - Vector atomsPicked = new Vector(); + /* + * state flag for PDB retrieval thread + */ + private boolean _started = false; private boolean addingStructures = false; - ViewSelectionMenu seqColourBy; + private IProgressIndicator progressBar = null; + + private String viewId = null; + + /* + * pdb retrieval thread. + */ + private Thread worker = null; /** - * - * @param files - * @param ids - * @param seqs - * @param ap - * @param usetoColour - * - add the alignment panel to the list used for colouring these - * structures - * @param useToAlign - * - add the alignment panel to the list used for aligning these - * structures - * @param leaveColouringToJmol - * - do not update the colours from any other source. Jmol is - * handling them - * @param loadStatus - * @param bounds - * @param viewid - * - * public ChimeraViewFrame(String[] files, String[] ids, - * SequenceI[][] seqs, AlignmentPanel ap, boolean usetoColour, - * boolean useToAlign, boolean leaveColouringToJmol, String - * loadStatus, Rectangle bounds, String viewid) { PDBEntry[] - * pdbentrys = new PDBEntry[files.length]; for (int i = 0; i < - * pdbentrys.length; i++) { PDBEntry pdbentry = new PDBEntry(); - * pdbentry.setFile(files[i]); pdbentry.setId(ids[i]); pdbentrys[i] = - * pdbentry; } // / TODO: check if protocol is needed to be set, and - * if chains are // autodiscovered. jmb = new - * JalviewChimeraBindingModel(this, - * ap.getStructureSelectionManager(), pdbentrys, seqs, null, null); - * - * jmb.setLoadingFromArchive(true); addAlignmentPanel(ap); if - * (useToAlign) { useAlignmentPanelForSuperposition(ap); } if - * (leaveColouringToJmol || !usetoColour) { - * jmb.setColourBySequence(false); seqColour.setSelected(false); - * jmolColour.setSelected(true); } if (usetoColour) { - * useAlignmentPanelForColourbyseq(ap); - * jmb.setColourBySequence(true); seqColour.setSelected(true); - * jmolColour.setSelected(false); } this.setBounds(bounds); - * initMenus(); viewId = viewid; // - * jalview.gui.Desktop.addInternalFrame(this, "Loading File", // - * bounds.width,bounds.height); - * - * this.addInternalFrameListener(new InternalFrameAdapter() { public - * void internalFrameClosing(InternalFrameEvent internalFrameEvent) { - * closeViewer(); } }); initJmol(loadStatus); // pdbentry, seq, - * JBPCHECK! - * - * } + * Initialise menu options. */ private void initMenus() { + viewerActionMenu.setText(MessageManager.getString("label.chimera")); + viewerColour.setText(MessageManager + .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()); - jmolColour.setSelected(!jmb.isColourBySequence()); + viewerColour.setSelected(!jmb.isColourBySequence()); if (_colourwith == null) { _colourwith = new Vector(); @@ -154,10 +144,10 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable, _alignwith = new Vector(); } - seqColourBy = new ViewSelectionMenu(MessageManager.getString("label.colour_by"), this, _colourwith, + ViewSelectionMenu seqColourBy = new ViewSelectionMenu( + MessageManager.getString("label.colour_by"), this, _colourwith, new ItemListener() { - @Override public void itemStateChanged(ItemEvent e) { @@ -167,17 +157,17 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable, } else { - // update the jmol display now. + // update the Chimera display now. seqColour_actionPerformed(null); } } }); viewMenu.add(seqColourBy); final ItemListener handler; - JMenu alpanels = new ViewSelectionMenu(MessageManager.getString("label.superpose_with"), this, + JMenu alpanels = new ViewSelectionMenu( + MessageManager.getString("label.superpose_with"), this, _alignwith, handler = new ItemListener() { - @Override public void itemStateChanged(ItemEvent e) { @@ -185,13 +175,13 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable, alignStructs.setToolTipText(MessageManager .formatMessage( "label.align_structures_using_linked_alignment_views", - new String[] + new Object[] { new Integer(_alignwith.size()).toString() })); } }); handler.itemStateChanged(null); - jmolActionMenu.add(alpanels); - jmolActionMenu.addMenuListener(new MenuListener() + viewerActionMenu.add(alpanels); + viewerActionMenu.addMenuListener(new MenuListener() { @Override @@ -204,22 +194,18 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable, public void menuDeselected(MenuEvent e) { // TODO Auto-generated method stub - } @Override public void menuCanceled(MenuEvent e) { // TODO Auto-generated method stub - } }); } - IProgressIndicator progressBar = null; - /** - * add a single PDB structure to a new or existing Jmol view + * add a single PDB structure to a new or existing Chimera view * * @param pdbentry * @param seq @@ -229,6 +215,7 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable, public ChimeraViewFrame(PDBEntry pdbentry, SequenceI[] seq, String[] chains, final AlignmentPanel ap) { + super(); progressBar = ap.alignFrame; // //////////////////////////////// // Is the pdb file already loaded? @@ -239,11 +226,16 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable, { int option = JOptionPane.showInternalConfirmDialog(Desktop.desktop, MessageManager.formatMessage( - "label.pdb_entry_is_already_displayed", new String[] + "label.pdb_entry_is_already_displayed", new Object[] { pdbentry.getId() }), MessageManager.formatMessage( - "label.map_sequences_to_visible_window", new String[] - { pdbentry.getId() }), JOptionPane.YES_NO_OPTION); + "label.map_sequences_to_visible_window", new Object[] + { pdbentry.getId() }), + JOptionPane.YES_NO_CANCEL_OPTION); + if (option == JOptionPane.CANCEL_OPTION) + { + return; + } if (option == JOptionPane.YES_OPTION) { // TODO : Fix multiple seq to one chain issue here. @@ -255,26 +247,26 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable, ap.paintAlignment(true); } - // Now this AppJmol is mapped to new sequences. We must add them to - // the exisiting array + // Now this ChimeraViewFrame is mapped to new sequences. We must add + // them to the existing array JInternalFrame[] frames = Desktop.instance.getAllFrames(); - for (int i = 0; i < frames.length; i++) + for (JInternalFrame frame : frames) { - if (frames[i] instanceof ChimeraViewFrame) + if (frame instanceof ChimeraViewFrame) { - final ChimeraViewFrame topJmol = ((ChimeraViewFrame) frames[i]); + final ChimeraViewFrame topView = ((ChimeraViewFrame) frame); // JBPNOTE: this looks like a binding routine, rather than a gui // routine - for (int pe = 0; pe < topJmol.jmb.pdbentry.length; pe++) + for (int pe = 0; pe < topView.jmb.pdbentry.length; pe++) { - if (topJmol.jmb.pdbentry[pe].getFile().equals(alreadyMapped)) + if (topView.jmb.pdbentry[pe].getFile().equals(alreadyMapped)) { - topJmol.jmb.addSequence(pe, seq); - topJmol.addAlignmentPanel(ap); + topView.jmb.addSequence(pe, seq); + topView.addAlignmentPanel(ap); // add it to the set used for colouring - topJmol.useAlignmentPanelForColourbyseq(ap); - topJmol.buildChimeraActionMenu(); + topView.useAlignmentPanelForColourbyseq(ap); + topView.buildChimeraActionMenu(); ap.getStructureSelectionManager() .sequenceColoursChanged(ap); break; @@ -287,40 +279,37 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable, } } // ///////////////////////////////// - // Check if there are other Jmol views involving this alignment + // Check if there are other Chimera views involving this alignment // and prompt user about adding this molecule to one of them - Vector existingViews = getJmolsFor(ap); - if (existingViews.size() > 0) + List existingViews = getChimeraWindowsFor(ap); + for (ChimeraViewFrame topView : existingViews) { - Enumeration jm = existingViews.elements(); - while (jm.hasMoreElements()) + // TODO: highlight topView in view somehow + int option = JOptionPane.showInternalConfirmDialog(Desktop.desktop, + MessageManager.formatMessage("label.add_pdbentry_to_view", + new Object[] + { pdbentry.getId(), topView.getTitle() }), + MessageManager + .getString("label.align_to_existing_structure_view"), + JOptionPane.YES_NO_CANCEL_OPTION); + if (option == JOptionPane.CANCEL_OPTION) { - ChimeraViewFrame topJmol = (ChimeraViewFrame) jm.nextElement(); - // TODO: highlight topJmol in view somehow - int option = JOptionPane - .showInternalConfirmDialog( - Desktop.desktop, - MessageManager.formatMessage( - "label.add_pdbentry_to_view", new String[] - { pdbentry.getId(), topJmol.getTitle() }), - MessageManager - .getString("label.align_to_existing_structure_view"), - JOptionPane.YES_NO_OPTION); - if (option == JOptionPane.YES_OPTION) - { - topJmol.useAlignmentPanelForSuperposition(ap); - topJmol.addStructure(pdbentry, seq, chains, true, ap.alignFrame); - return; - } + return; + } + if (option == JOptionPane.YES_OPTION) + { + topView.useAlignmentPanelForSuperposition(ap); + topView.addStructure(pdbentry, seq, chains, true, ap.alignFrame); + return; } } // ///////////////////////////////// - openNewJmol(ap, new PDBEntry[] + openNewChimera(ap, new PDBEntry[] { pdbentry }, new SequenceI[][] { seq }); } - private void openNewJmol(AlignmentPanel ap, PDBEntry[] pdbentrys, + private void openNewChimera(AlignmentPanel ap, PDBEntry[] pdbentrys, SequenceI[][] seqs) { progressBar = ap.alignFrame; @@ -353,7 +342,7 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable, } /** - * create a new Jmol containing several structures superimposed using the + * create a new viewer containing several structures superimposed using the * given alignPanel. * * @param ap @@ -363,14 +352,10 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable, public ChimeraViewFrame(AlignmentPanel ap, PDBEntry[] pe, SequenceI[][] seqs) { - openNewJmol(ap, pe, seqs); + super(); + openNewChimera(ap, pe, seqs); } - /** - * list of sequenceSet ids associated with the view - */ - ArrayList _aps = new ArrayList(); - public AlignmentPanel[] getAllAlignmentPanels() { AlignmentPanel[] t, list = new AlignmentPanel[0]; @@ -390,17 +375,6 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable, } /** - * list of alignment panels to use for superposition - */ - Vector _alignwith = new Vector(); - - /** - * list of alignment panels that are used for colouring structures by aligned - * sequences - */ - Vector _colourwith = new Vector(); - - /** * set the primary alignmentPanel reference and add another alignPanel to the * list of ones to use for colouring and aligning * @@ -473,7 +447,7 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable, useAlignmentPanelForColourbyseq(nap); jmb.setColourBySequence(enableColourBySeq); seqColour.setSelected(enableColourBySeq); - jmolColour.setSelected(!enableColourBySeq); + viewerColour.setSelected(!enableColourBySeq); } public void useAlignmentPanelForColourbyseq(AlignmentPanel nap) @@ -494,11 +468,6 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable, } /** - * pdb retrieval thread. - */ - private Thread worker = null; - - /** * add a new structure (with associated sequences and chains) to this viewer, * retrieving it if necessary first. * @@ -554,25 +523,22 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable, return; } - private Vector getJmolsFor(AlignmentPanel ap2) + private List getChimeraWindowsFor(AlignmentPanel apanel) { - Vector otherJmols = new Vector(); - // Now this AppJmol is mapped to new sequences. We must add them to - // the exisiting array + List result = new ArrayList(); JInternalFrame[] frames = Desktop.instance.getAllFrames(); - for (int i = 0; i < frames.length; i++) + for (JInternalFrame frame : frames) { - if (frames[i] instanceof ChimeraViewFrame) + if (frame instanceof ChimeraViewFrame) { - ChimeraViewFrame topJmol = ((ChimeraViewFrame) frames[i]); - if (topJmol.isLinkedWith(ap2)) + if (((ChimeraViewFrame) frame).isLinkedWith(apanel)) { - otherJmols.addElement(topJmol); + result.add((ChimeraViewFrame) frame); } } } - return otherJmols; + return result; } void initChimera(String command) @@ -590,10 +556,10 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable, jmb.setFinishedInit(true); } - void setChainMenuItems(Vector chains) + void setChainMenuItems(List chainNames) { chainMenu.removeAll(); - if (chains == null) + if (chainNames == null) { return; } @@ -607,7 +573,9 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable, for (int i = 0; i < chainMenu.getItemCount(); i++) { if (chainMenu.getItem(i) instanceof JCheckBoxMenuItem) + { ((JCheckBoxMenuItem) chainMenu.getItem(i)).setSelected(true); + } } centerViewer(); allChainsSelected = false; @@ -616,15 +584,17 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable, chainMenu.add(menuItem); - for (int c = 0; c < chains.size(); c++) + for (String chainName : chainNames) { - menuItem = new JCheckBoxMenuItem(chains.elementAt(c).toString(), true); + menuItem = new JCheckBoxMenuItem(chainName, true); menuItem.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent evt) { if (!allChainsSelected) + { centerViewer(); + } } }); @@ -632,15 +602,9 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable, } } - boolean allChainsSelected = false; - - private boolean alignAddedStructures = false; - void centerViewer() { - Vector toshow = new Vector(); - String lbl; - int mlength, p, mnum; + List toshow = new ArrayList(); for (int i = 0; i < chainMenu.getItemCount(); i++) { if (chainMenu.getItem(i) instanceof JCheckBoxMenuItem) @@ -648,7 +612,7 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable, JCheckBoxMenuItem item = (JCheckBoxMenuItem) chainMenu.getItem(i); if (item.isSelected()) { - toshow.addElement(item.getText()); + toshow.add(item.getText()); } } } @@ -668,73 +632,45 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable, } /** - * state flag for PDB retrieval thread + * Open any newly added PDB structures in Chimera, having first fetched data + * from PDB (if not already saved). */ - private boolean _started = false; - public void run() { _started = true; - String pdbid = ""; - // todo - record which pdbids were successfuly imported. - StringBuffer errormsgs = new StringBuffer(), files = new StringBuffer(); - List fileToLoad=new ArrayList(); + // todo - record which pdbids were successfully imported. + StringBuilder errormsgs = new StringBuilder(128); + StringBuilder files = new StringBuilder(128); List filePDB = new ArrayList(); - List filePDBpos =new ArrayList(); + List filePDBpos = new ArrayList(); + PDBEntry thePdbEntry = null; try { String[] curfiles = jmb.getPdbFile(); // files currently in viewer // TODO: replace with reference fetching/transfer code (validate PDBentry // as a DBRef?) - jalview.ws.dbsources.Pdb pdbclient = new jalview.ws.dbsources.Pdb(); for (int pi = 0; pi < jmb.pdbentry.length; pi++) { String file = null; - if (jmb.pdbentry[pi].getFile()==null) + thePdbEntry = jmb.pdbentry[pi]; + if (thePdbEntry.getFile() == null) { - // retrieve the pdb and store it locally - AlignmentI pdbseq = null; - pdbid = jmb.pdbentry[pi].getId(); - long hdl = pdbid.hashCode() - System.currentTimeMillis(); - if (progressBar != null) - { - progressBar.setProgressBar(MessageManager.formatMessage("status.fetching_pdb", new String[]{pdbid}), hdl); - } - try - { - pdbseq = pdbclient.getSequenceRecords(pdbid = jmb.pdbentry[pi] - .getId()); - } catch (OutOfMemoryError oomerror) - { - new OOMWarning("Retrieving PDB id " + pdbid, oomerror); - } catch (Exception ex) - { - ex.printStackTrace(); - errormsgs.append("'" + pdbid + "'"); - } - if (progressBar != null) - { - progressBar.setProgressBar(MessageManager.getString("label.state_completed"), hdl); - } - if (pdbseq != null) + /* + * Retrieve PDB data, save to file, attach to PDBEntry + */ + file = fetchPdbFile(thePdbEntry); + if (file == null) { - // just transfer the file name from the first sequence's first - // PDBEntry - file = new File(((PDBEntry) pdbseq.getSequenceAt(0).getPDBId() - .elementAt(0)).getFile()).getAbsolutePath(); - jmb.pdbentry[pi].setFile(file); - - files.append(" \"" + Platform.escapeString(file) + "\""); - } - else - { - errormsgs.append("'" + pdbid + "' "); + errormsgs.append("'" + thePdbEntry.getId() + "' "); } } else { - file = new File(jmb.pdbentry[pi].getFile()) - .getAbsoluteFile().getPath(); + /* + * Got file already - ignore if already loaded in Chimera. + */ + file = new File(thePdbEntry.getFile()).getAbsoluteFile() + .getPath(); if (curfiles != null && curfiles.length > 0) { addingStructures = true; // already files loaded. @@ -747,37 +683,35 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable, } } } - - if (file != null) - { - fileToLoad.add(file); - filePDB.add(jmb.pdbentry[pi]); - filePDBpos.add(Integer.valueOf(pi)); - files.append(" \"" + Platform.escapeString(file) + "\""); - } + } + if (file != null) + { + filePDB.add(thePdbEntry); + filePDBpos.add(Integer.valueOf(pi)); + files.append(" \"" + Platform.escapeString(file) + "\""); } } } catch (OutOfMemoryError oomerror) { - new OOMWarning("Retrieving PDB files: " + pdbid, oomerror); + new OOMWarning("Retrieving PDB files: " + thePdbEntry.getId(), + oomerror); } catch (Exception ex) { ex.printStackTrace(); - errormsgs.append("When retrieving pdbfiles : current was: '" + pdbid - + "'"); + errormsgs.append("When retrieving pdbfiles : current was: '" + + thePdbEntry.getId() + "'"); } if (errormsgs.length() > 0) { JOptionPane.showInternalMessageDialog(Desktop.desktop, MessageManager .formatMessage("label.pdb_entries_couldnt_be_retrieved", - new String[] + new Object[] { errormsgs.toString() }), MessageManager .getString("label.couldnt_load_file"), JOptionPane.ERROR_MESSAGE); - } - long lastnotify = jmb.getLoadNotifiesHandled(); + if (files.length() > 0) { if (!addingStructures) @@ -789,8 +723,8 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable, { Cache.log.error("Couldn't open Chimera viewer!", ex); } - } - int num=-1; + } + int num = -1; for (PDBEntry pe : filePDB) { num++; @@ -798,26 +732,24 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable, { try { - int pos=filePDBpos.get(num).intValue(); + int pos = filePDBpos.get(num).intValue(); jmb.openFile(pe); jmb.addSequence(pos, jmb.sequence[pos]); - File fl=new File(pe.getFile()); + File fl = new File(pe.getFile()); String protocol = AppletFormatAdapter.URL; try { if (fl.exists()) - { - protocol = AppletFormatAdapter.FILE; - } - } catch (Exception e) - { - } catch (Error e) { + protocol = AppletFormatAdapter.FILE; } - // Explicitly map to the filename used by Jmol ; - jmb.ssm.setMapping(jmb.sequence[pos], null, pe.getFile(), - protocol); - // pdbentry[pe].getFile(), protocol); + } catch (Throwable e) + { + } + // Explicitly map to the filename used by Chimera ; + // TODO: use pe.getId() instead of pe.getFile() ? + jmb.ssm.setMapping(jmb.sequence[pos], null, pe.getFile(), + protocol); } catch (OutOfMemoryError oomerror) { new OOMWarning( @@ -833,10 +765,9 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable, } } } - // jmb.getPdbFile(); jmb.setFinishedInit(true); jmb.setLoadingFromArchive(false); - + // refresh the sequence colours for the new structure(s) for (AlignmentPanel ap : _colourwith) { @@ -860,6 +791,54 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable, worker = null; } + /** + * Fetch PDB data and save to a local file. Returns the full path to the file, + * or null if fetch fails. + * + * @param processingEntry + * @return + * @throws Exception + */ + private String fetchPdbFile(PDBEntry processingEntry) throws Exception + { + String filePath = null; + Pdb pdbclient = new Pdb(); + AlignmentI pdbseq = null; + String pdbid = processingEntry.getId(); + long hdl = pdbid.hashCode() - System.currentTimeMillis(); + if (progressBar != null) + { + progressBar.setProgressBar(MessageManager.formatMessage( + "status.fetching_pdb", new Object[] + { pdbid }), hdl); + } + try + { + pdbseq = pdbclient.getSequenceRecords(pdbid); + } catch (OutOfMemoryError oomerror) + { + new OOMWarning("Retrieving PDB id " + pdbid, oomerror); + } + if (progressBar != null) + { + progressBar.setProgressBar( + MessageManager.getString("label.state_completed"), hdl); + } + /* + * If PDB data were saved and are not invalid (empty alignment), return the + * file path. + */ + if (pdbseq != null && pdbseq.getHeight() > 0) + { + // just use the file name from the first sequence's first PDBEntry + filePath = new File(((PDBEntry) pdbseq.getSequenceAt(0).getPDBId() + .elementAt(0)).getFile()).getAbsolutePath(); + processingEntry.setFile(filePath); + } + return filePath; + } + + @Override public void pdbFile_actionPerformed(ActionEvent actionEvent) { JalviewFileChooser chooser = new JalviewFileChooser( @@ -873,11 +852,11 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable, if (value == JalviewFileChooser.APPROVE_OPTION) { + BufferedReader in = null; try { // TODO: cope with multiple PDB files in view - BufferedReader in = new BufferedReader(new FileReader( - jmb.getPdbFile()[0])); + in = new BufferedReader(new FileReader(jmb.getPdbFile()[0])); File outFile = chooser.getSelectedFile(); PrintWriter out = new PrintWriter(new FileOutputStream(outFile)); @@ -893,10 +872,23 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable, } catch (Exception ex) { ex.printStackTrace(); + } finally + { + if (in != null) + { + try + { + in.close(); + } catch (IOException e) + { + e.printStackTrace(); + } + } } } } + @Override public void viewMapping_actionPerformed(ActionEvent actionEvent) { jalview.gui.CutAndPasteTransfer cap = new jalview.gui.CutAndPasteTransfer(); @@ -920,37 +912,33 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable, 600); } - /** - * DOCUMENT ME! - * - * @param e - * DOCUMENT ME! - */ + @Override public void eps_actionPerformed(ActionEvent e) { - throw new Error(MessageManager.getString("error.eps_generation_not_implemented")); + throw new Error( + MessageManager + .getString("error.eps_generation_not_implemented")); } - /** - * DOCUMENT ME! - * - * @param e - * DOCUMENT ME! - */ + @Override public void png_actionPerformed(ActionEvent e) { - throw new Error(MessageManager.getString("error.png_generation_not_implemented")); + throw new Error( + MessageManager + .getString("error.png_generation_not_implemented")); } - public void jmolColour_actionPerformed(ActionEvent actionEvent) + @Override + public void viewerColour_actionPerformed(ActionEvent actionEvent) { - if (jmolColour.isSelected()) + if (viewerColour.isSelected()) { // disable automatic sequence colouring. jmb.setColourBySequence(false); } } + @Override public void seqColour_actionPerformed(ActionEvent actionEvent) { jmb.setColourBySequence(seqColour.isSelected()); @@ -976,82 +964,96 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable, } } + @Override public void chainColour_actionPerformed(ActionEvent actionEvent) { chainColour.setSelected(true); jmb.colourByChain(); } + @Override public void chargeColour_actionPerformed(ActionEvent actionEvent) { chargeColour.setSelected(true); jmb.colourByCharge(); } + @Override public void zappoColour_actionPerformed(ActionEvent actionEvent) { zappoColour.setSelected(true); jmb.setJalviewColourScheme(new ZappoColourScheme()); } + @Override public void taylorColour_actionPerformed(ActionEvent actionEvent) { taylorColour.setSelected(true); jmb.setJalviewColourScheme(new TaylorColourScheme()); } + @Override public void hydroColour_actionPerformed(ActionEvent actionEvent) { hydroColour.setSelected(true); jmb.setJalviewColourScheme(new HydrophobicColourScheme()); } + @Override public void helixColour_actionPerformed(ActionEvent actionEvent) { helixColour.setSelected(true); jmb.setJalviewColourScheme(new HelixColourScheme()); } + @Override public void strandColour_actionPerformed(ActionEvent actionEvent) { strandColour.setSelected(true); jmb.setJalviewColourScheme(new StrandColourScheme()); } + @Override public void turnColour_actionPerformed(ActionEvent actionEvent) { turnColour.setSelected(true); jmb.setJalviewColourScheme(new TurnColourScheme()); } + @Override public void buriedColour_actionPerformed(ActionEvent actionEvent) { buriedColour.setSelected(true); jmb.setJalviewColourScheme(new BuriedColourScheme()); } + @Override public void purinePyrimidineColour_actionPerformed(ActionEvent actionEvent) { setJalviewColourScheme(new PurinePyrimidineColourScheme()); } + @Override public void userColour_actionPerformed(ActionEvent actionEvent) { userColour.setSelected(true); new UserDefinedColours(this, null); } + @Override public void backGround_actionPerformed(ActionEvent actionEvent) { - java.awt.Color col = JColorChooser.showDialog(this, - MessageManager.getString("label.select_backgroud_colour"), null); + java.awt.Color col = JColorChooser + .showDialog(this, MessageManager + .getString("label.select_backgroud_colour"), null); if (col != null) { jmb.setBackgroundColour(col); } } - public void jmolHelp_actionPerformed(ActionEvent actionEvent) + @Override + public void showHelp_actionPerformed(ActionEvent actionEvent) { try { @@ -1062,8 +1064,6 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable, } } - String viewId = null; - public String getViewId() { if (viewId == null) @@ -1085,7 +1085,7 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable, this.setTitle(jmb.getViewerTitle()); if (jmb.getPdbFile().length > 1 && jmb.sequence.length > 1) { - jmolActionMenu.setVisible(true); + viewerActionMenu.setVisible(true); } if (!jmb.isLoadingFromArchive()) { @@ -1104,14 +1104,13 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable, _alignwith.add(ap); } ; - for (Component c : jmolActionMenu.getMenuComponents()) + for (Component c : viewerActionMenu.getMenuComponents()) { if (c != alignStructs) { - jmolActionMenu.remove((JMenuItem) c); + viewerActionMenu.remove((JMenuItem) c); } } - final ItemListener handler; } /* @@ -1194,7 +1193,7 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable, /** * * @param ap2 - * @return true if this Jmol instance is linked with the given alignPanel + * @return true if this Chimera instance is linked with the given alignPanel */ public boolean isLinkedWith(AlignmentPanel ap2) { @@ -1216,7 +1215,7 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable, * * @return TRUE if the view is NOT being coloured by sequence associations. */ - public boolean isColouredByJmol() + public boolean isColouredByChimera() { return !jmb.isColourBySequence(); } diff --git a/src/jalview/jbgui/GStructureViewer.java b/src/jalview/jbgui/GStructureViewer.java index f6c4e05..7e1be58 100644 --- a/src/jalview/jbgui/GStructureViewer.java +++ b/src/jalview/jbgui/GStructureViewer.java @@ -22,9 +22,15 @@ package jalview.jbgui; import jalview.util.MessageManager; -import javax.swing.*; -import java.awt.event.ActionListener; import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.ButtonGroup; +import javax.swing.JInternalFrame; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JRadioButtonMenuItem; public class GStructureViewer extends JInternalFrame { @@ -189,24 +195,25 @@ public class GStructureViewer extends JInternalFrame userColour_actionPerformed(actionEvent); } }); - jmolColour.setSelected(false); - jmolColour.setText(MessageManager.getString("label.colour_with_jmol")); - jmolColour.setToolTipText(MessageManager + viewerColour.setSelected(false); + viewerColour + .setText(MessageManager.getString("label.colour_with_jmol")); + viewerColour.setToolTipText(MessageManager .getString("label.let_jmol_manage_structure_colours")); - jmolColour.addActionListener(new ActionListener() + viewerColour.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent actionEvent) { - jmolColour_actionPerformed(actionEvent); + viewerColour_actionPerformed(actionEvent); } }); helpMenu.setText(MessageManager.getString("action.help")); - jmolHelp.setText(MessageManager.getString("label.jmol_help")); - jmolHelp.addActionListener(new ActionListener() + helpItem.setText(MessageManager.getString("label.jmol_help")); + helpItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent actionEvent) { - jmolHelp_actionPerformed(actionEvent); + showHelp_actionPerformed(actionEvent); } }); alignStructs @@ -218,12 +225,12 @@ public class GStructureViewer extends JInternalFrame alignStructs_actionPerformed(actionEvent); } }); - jmolActionMenu.setText(MessageManager.getString("label.jmol")); + viewerActionMenu.setText(MessageManager.getString("label.jmol")); menuBar.add(fileMenu); menuBar.add(viewMenu); menuBar.add(colourMenu); - menuBar.add(jmolActionMenu); - jmolActionMenu.setVisible(false); + menuBar.add(viewerActionMenu); + viewerActionMenu.setVisible(false); menuBar.add(helpMenu); fileMenu.add(savemenu); fileMenu.add(viewMapping); @@ -244,7 +251,7 @@ public class GStructureViewer extends JInternalFrame colourMenu.add(buriedColour); colourMenu.add(purinePyrimidineColour); colourMenu.add(userColour); - colourMenu.add(jmolColour); + colourMenu.add(viewerColour); colourMenu.add(backGround); colourButtons.add(seqColour); @@ -258,13 +265,13 @@ public class GStructureViewer extends JInternalFrame colourButtons.add(turnColour); colourButtons.add(buriedColour); colourButtons.add(userColour); - colourButtons.add(jmolColour); + colourButtons.add(viewerColour); - helpMenu.add(jmolHelp); - jmolActionMenu.add(alignStructs); + helpMenu.add(helpItem); + viewerActionMenu.add(alignStructs); } - protected void jmolColour_actionPerformed(ActionEvent actionEvent) + protected void viewerColour_actionPerformed(ActionEvent actionEvent) { } @@ -294,7 +301,7 @@ public class GStructureViewer extends JInternalFrame protected JMenu colourMenu = new JMenu(); - protected JMenu jmolActionMenu = new JMenu(); + protected JMenu viewerActionMenu = new JMenu(); protected JMenuItem alignStructs = new JMenuItem(); @@ -324,13 +331,13 @@ public class GStructureViewer extends JInternalFrame protected JRadioButtonMenuItem userColour = new JRadioButtonMenuItem(); - protected JRadioButtonMenuItem jmolColour = new JRadioButtonMenuItem(); + protected JRadioButtonMenuItem viewerColour = new JRadioButtonMenuItem(); protected ButtonGroup colourButtons = new ButtonGroup(); JMenu helpMenu = new JMenu(); - JMenuItem jmolHelp = new JMenuItem(); + protected JMenuItem helpItem = new JMenuItem(); public void pdbFile_actionPerformed(ActionEvent actionEvent) { @@ -417,7 +424,7 @@ public class GStructureViewer extends JInternalFrame } - public void jmolHelp_actionPerformed(ActionEvent actionEvent) + public void showHelp_actionPerformed(ActionEvent actionEvent) { } diff --git a/src/jalview/structure/StructureSelectionManager.java b/src/jalview/structure/StructureSelectionManager.java index 175a249..ac2897d 100644 --- a/src/jalview/structure/StructureSelectionManager.java +++ b/src/jalview/structure/StructureSelectionManager.java @@ -360,11 +360,13 @@ public class StructureSelectionManager + maxChain.residues.size() + "\n\n"); PrintStream ps = new PrintStream(System.out) { + @Override public void print(String x) { mappingDetails.append(x); } + @Override public void println() { mappingDetails.append("\n");