X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fgui%2FChimeraViewFrame.java;h=4c38898604f817da581651a6f72f796f3a88c758;hb=5965127c38ff1a35d10d806c4b4537cdc1e39579;hp=1915936dc7ecdb137a88fbfc7a36c855ccb44c0a;hpb=3bc2fbe640abb0d8941aead117c9624dd16773a3;p=jalview.git diff --git a/src/jalview/gui/ChimeraViewFrame.java b/src/jalview/gui/ChimeraViewFrame.java index 1915936..4c38898 100644 --- a/src/jalview/gui/ChimeraViewFrame.java +++ b/src/jalview/gui/ChimeraViewFrame.java @@ -20,21 +20,51 @@ */ package jalview.gui; +import jalview.bin.Cache; +import jalview.datamodel.Alignment; +import jalview.datamodel.AlignmentI; +import jalview.datamodel.ColumnSelection; +import jalview.datamodel.PDBEntry; +import jalview.datamodel.SequenceI; +import jalview.ext.rbvi.chimera.ChimeraCommands; +import jalview.ext.rbvi.chimera.JalviewChimeraBinding; +import jalview.gui.StructureViewer.ViewerType; +import jalview.io.DataSourceType; +import jalview.io.JalviewFileChooser; +import jalview.io.JalviewFileView; +import jalview.io.StructureFile; +import jalview.schemes.BuriedColourScheme; +import jalview.schemes.ColourSchemeI; +import jalview.schemes.HelixColourScheme; +import jalview.schemes.HydrophobicColourScheme; +import jalview.schemes.PurinePyrimidineColourScheme; +import jalview.schemes.StrandColourScheme; +import jalview.schemes.TaylorColourScheme; +import jalview.schemes.TurnColourScheme; +import jalview.schemes.ZappoColourScheme; +import jalview.structures.models.AAStructureBindingModel; +import jalview.util.MessageManager; +import jalview.util.Platform; +import jalview.ws.dbsources.Pdb; + import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; import java.io.BufferedReader; import java.io.File; +import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; +import java.io.InputStream; import java.io.PrintWriter; import java.util.ArrayList; +import java.util.Collections; import java.util.List; -import java.util.Map; import java.util.Random; -import java.util.Set; import java.util.Vector; import javax.swing.JCheckBoxMenuItem; @@ -48,30 +78,6 @@ import javax.swing.event.InternalFrameEvent; import javax.swing.event.MenuEvent; import javax.swing.event.MenuListener; -import jalview.bin.Cache; -import jalview.datamodel.Alignment; -import jalview.datamodel.AlignmentI; -import jalview.datamodel.ColumnSelection; -import jalview.datamodel.PDBEntry; -import jalview.datamodel.SequenceI; -import jalview.ext.rbvi.chimera.JalviewChimeraBinding; -import jalview.io.AppletFormatAdapter; -import jalview.io.JalviewFileChooser; -import jalview.io.JalviewFileView; -import jalview.schemes.BuriedColourScheme; -import jalview.schemes.ColourSchemeI; -import jalview.schemes.HelixColourScheme; -import jalview.schemes.HydrophobicColourScheme; -import jalview.schemes.PurinePyrimidineColourScheme; -import jalview.schemes.StrandColourScheme; -import jalview.schemes.TaylorColourScheme; -import jalview.schemes.TurnColourScheme; -import jalview.schemes.ZappoColourScheme; -import jalview.structures.models.AAStructureBindingModel; -import jalview.util.MessageManager; -import jalview.util.Platform; -import jalview.ws.dbsources.Pdb; - /** * GUI elements for handling an external chimera display * @@ -84,23 +90,9 @@ public class ChimeraViewFrame extends StructureViewerBase private boolean allChainsSelected = false; - private boolean alignAddedStructures = false; - - /* - * state flag for PDB retrieval thread - */ - private boolean _started = false; - - private boolean addingStructures = false; - private IProgressIndicator progressBar = null; /* - * pdb retrieval thread. - */ - private Thread worker = null; - - /* * Path to Chimera session file. This is set when an open Jalview/Chimera * session is saved, or on restore from a Jalview project (if it holds the * filename of any saved Chimera sessions). @@ -167,8 +159,8 @@ public class ChimeraViewFrame extends StructureViewerBase alignStructs.setToolTipText(MessageManager .formatMessage( "label.align_structures_using_linked_alignment_views", - new Object[] - { new Integer(_alignwith.size()).toString() })); + new Object[] { new Integer(_alignwith + .size()).toString() })); } }); handler.itemStateChanged(null); @@ -194,172 +186,137 @@ public class ChimeraViewFrame extends StructureViewerBase // TODO Auto-generated method stub } }); + + JMenuItem writeFeatures = new JMenuItem( + MessageManager.getString("label.create_chimera_attributes")); + writeFeatures.setToolTipText(MessageManager + .getString("label.create_chimera_attributes_tip")); + writeFeatures.addActionListener(new ActionListener() + { + @Override + public void actionPerformed(ActionEvent e) + { + sendFeaturesToChimera(); + } + }); + viewerActionMenu.add(writeFeatures); + + final JMenu fetchAttributes = new JMenu("Fetch Chimera attributes"); + fetchAttributes + .setToolTipText("Copy Chimera attribute to Jalview feature"); + fetchAttributes.addMouseListener(new MouseAdapter() + { + + @Override + public void mouseEntered(MouseEvent e) + { + buildAttributesMenu(fetchAttributes); + } + }); + viewerActionMenu.add(fetchAttributes); + } /** - * add a single PDB structure to a new or existing Chimera view + * Query Chimera for its residue attribute names and add them as items off the + * attributes menu * - * @param pdbentry - * @param seq - * @param chains - * @param ap + * @param attributesMenu */ - public ChimeraViewFrame(PDBEntry pdbentry, SequenceI[] seq, - String[] chains, final AlignmentPanel ap) + protected void buildAttributesMenu(JMenu attributesMenu) { - super(); - - /* - * is the pdb file already loaded? - */ - String pdbId = pdbentry.getId(); - String alreadyMapped = ap.getStructureSelectionManager() - .alreadyMappedToFile(pdbId); - - if (alreadyMapped != null) + List atts = jmb.sendChimeraCommand("list resattr", true); + if (atts == null) { - int option = chooseAddSequencesToViewer(pdbId); - if (option == JOptionPane.CANCEL_OPTION) - { - return; - } - if (option == JOptionPane.YES_OPTION) - { - addSequenceMappingsToStructure(seq, chains, ap, alreadyMapped); - return; - } + return; } - - /* - * Check if there are other Chimera views involving this alignment and give - * user the option to add and align this molecule to one of them - */ - List existingViews = getChimeraWindowsFor(ap); - for (ChimeraViewFrame view : existingViews) + attributesMenu.removeAll(); + Collections.sort(atts); + for (String att : atts) { - // TODO: highlight view somehow + final String attName = att.split(" ")[1]; + /* - * JAL-1742 exclude view with this structure already mapped (don't offer - * to align chain B to chain A of the same structure) + * ignore 'jv_*' attributes, as these are Jalview features that have + * been transferred to residue attributes in Chimera! */ - if (view.hasPdbId(pdbId)) - { - continue; - } - int option = chooseAlignStructureToViewer(pdbId, view); - if (option == JOptionPane.CANCEL_OPTION) - { - return; - } - if (option == JOptionPane.YES_OPTION) + if (!attName.startsWith(ChimeraCommands.NAMESPACE_PREFIX)) { - view.useAlignmentPanelForSuperposition(ap); - view.addStructure(pdbentry, seq, chains, true, ap.alignFrame); - return; + JMenuItem menuItem = new JMenuItem(attName); + menuItem.addActionListener(new ActionListener() + { + @Override + public void actionPerformed(ActionEvent e) + { + getChimeraAttributes(attName); + } + }); + attributesMenu.add(menuItem); } } - - /* - * If the options above are declined or do not apply, open a new viewer - */ - openNewChimera(ap, new PDBEntry[] - { pdbentry }, new SequenceI[][] - { seq }); } /** - * Presents a dialog with the option to add an align a structure to an - * existing Chimera view + * Read residues in Chimera with the given attribute name, and set as features + * on the corresponding sequence positions (if any) * - * @param pdbId - * @param view - * @return YES, NO or CANCEL JOptionPane code + * @param attName */ - protected int chooseAlignStructureToViewer(String pdbId, - ChimeraViewFrame view) + protected void getChimeraAttributes(String attName) { - int option = JOptionPane.showInternalConfirmDialog(Desktop.desktop, - MessageManager.formatMessage("label.add_pdbentry_to_view", - new Object[] - { pdbId, view.getTitle() }), MessageManager - .getString("label.align_to_existing_structure_view"), - JOptionPane.YES_NO_CANCEL_OPTION); - return option; + jmb.copyStructureAttributesToFeatures(attName, getAlignmentPanel()); } /** - * Presents a dialog with the option to add sequences to a viewer which - * already has their structure open - * - * @param pdbId - * @return YES, NO or CANCEL JOptionPane code + * Send a command to Chimera to create residue attributes for Jalview features + *

+ * The syntax is: setattr r + *

+ * For example: setattr r jv:chain "Ferredoxin-1, Chloroplastic" #0:94.A */ - protected int chooseAddSequencesToViewer(String pdbId) + protected void sendFeaturesToChimera() { - int option = JOptionPane.showInternalConfirmDialog(Desktop.desktop, - MessageManager.formatMessage( - "label.pdb_entry_is_already_displayed", new Object[] - { pdbId }), MessageManager.formatMessage( - "label.map_sequences_to_visible_window", new Object[] - { pdbId }), JOptionPane.YES_NO_CANCEL_OPTION); - return option; + jmb.sendFeaturesToViewer(getAlignmentPanel()); } /** - * Adds mappings for the given sequences to an already opened PDB structure, - * and updates any viewers that have the PDB file + * add a single PDB structure to a new or existing Chimera view * + * @param pdbentry * @param seq * @param chains * @param ap - * @param pdbFilename */ - protected void addSequenceMappingsToStructure(SequenceI[] seq, - String[] chains, final AlignmentPanel ap, String pdbFilename) + public ChimeraViewFrame(PDBEntry pdbentry, SequenceI[] seq, + String[] chains, final AlignmentPanel ap) { - // TODO : Fix multiple seq to one chain issue here. - /* - * create the mappings - */ - ap.getStructureSelectionManager().setMapping(seq, chains, pdbFilename, - AppletFormatAdapter.FILE); + this(); + String pdbId = pdbentry.getId(); /* - * alert the FeatureRenderer to show new (PDB RESNUM) features + * If the PDB file is already loaded, the user may just choose to add to an + * existing viewer (or cancel) */ - if (ap.getSeqPanel().seqCanvas.fr != null) + if (addAlreadyLoadedFile(seq, chains, ap, pdbId)) { - ap.getSeqPanel().seqCanvas.fr.featuresAdded(); - ap.paintAlignment(true); + return; } /* - * add the sequences to any other Chimera viewers for this pdb file + * Check if there are other Chimera views involving this alignment and give + * user the option to add and align this molecule to one of them (or cancel) */ - // JBPNOTE: this looks like a binding routine, rather than a gui routine - for (JInternalFrame frame : Desktop.instance.getAllFrames()) + if (addToExistingViewer(pdbentry, seq, chains, ap, pdbId)) { - if (frame instanceof ChimeraViewFrame) - { - ChimeraViewFrame chimeraView = ((ChimeraViewFrame) frame); - for (int pe = 0; pe < chimeraView.jmb.getPdbCount(); pe++) - { - if (chimeraView.jmb.getPdbEntry(pe).getFile().equals(pdbFilename)) - { - chimeraView.jmb.addSequence(pe, seq); - chimeraView.addAlignmentPanel(ap); - /* - * add it to the set of alignments used for colouring structure by - * sequence - */ - chimeraView.useAlignmentPanelForColourbyseq(ap); - chimeraView.buildActionMenu(); - ap.getStructureSelectionManager().sequenceColoursChanged(ap); - break; - } - } - } + return; } + + /* + * If the options above are declined or do not apply, show the structure in + * a new viewer + */ + openNewChimera(ap, new PDBEntry[] { pdbentry }, + new SequenceI[][] { seq }); } /** @@ -373,6 +330,10 @@ public class ChimeraViewFrame extends StructureViewerBase } } + /** + * Answers true if this viewer already involves the given PDB ID + */ + @Override protected boolean hasPdbId(String pdbId) { return jmb.hasPdbId(pdbId); @@ -382,10 +343,8 @@ public class ChimeraViewFrame extends StructureViewerBase SequenceI[][] seqs) { createProgressBar(); - String[][] chains = extractChains(seqs); jmb = new JalviewChimeraBindingModel(this, - ap.getStructureSelectionManager(), pdbentrys, seqs, chains, - null); + ap.getStructureSelectionManager(), pdbentrys, seqs, null); addAlignmentPanel(ap); useAlignmentPanelForColourbyseq(ap); if (pdbentrys.length > 1) @@ -403,6 +362,7 @@ public class ChimeraViewFrame extends StructureViewerBase this.addInternalFrameListener(new InternalFrameAdapter() { + @Override public void internalFrameClosing(InternalFrameEvent internalFrameEvent) { closeViewer(false); @@ -412,56 +372,25 @@ public class ChimeraViewFrame extends StructureViewerBase } /** - * Retrieve chains for sequences by inspecting their PDB refs. The hope is - * that the first will be to the sequence's own chain. Really need a more - * managed way of doing this. - * - * @param seqs - * @return - */ - protected String[][] extractChains(SequenceI[][] seqs) - { - String[][] chains = new String[seqs.length][]; - for (int i = 0; i < seqs.length; i++) - { - chains[i] = new String[seqs[i].length]; - int seqno = 0; - for (SequenceI seq : seqs[i]) - { - String chain = null; - if (seq.getDatasetSequence() != null) - { - Vector pdbrefs = seq.getDatasetSequence().getPDBId(); - if (pdbrefs != null && pdbrefs.size() > 0) - { - chain = pdbrefs.get(0).getChainCode(); - } - } - chains[i][seqno++] = chain; - } - } - return chains; - } - - /** * Create a new viewer from saved session state data including Chimera session - * file. - * - * @param chimeraSession + * file * + * @param chimeraSessionFile * @param alignPanel * @param pdbArray * @param seqsArray * @param colourByChimera * @param colourBySequence + * @param newViewId */ - public ChimeraViewFrame(String chimeraSession, AlignmentPanel alignPanel, - PDBEntry[] pdbArray, + public ChimeraViewFrame(String chimeraSessionFile, + AlignmentPanel alignPanel, PDBEntry[] pdbArray, SequenceI[][] seqsArray, boolean colourByChimera, - boolean colourBySequence) + boolean colourBySequence, String newViewId) { - super(); - this.chimeraSessionFile = chimeraSession; + this(); + setViewId(newViewId); + this.chimeraSessionFile = chimeraSessionFile; openNewChimera(alignPanel, pdbArray, seqsArray); if (colourByChimera) { @@ -488,101 +417,41 @@ public class ChimeraViewFrame extends StructureViewerBase public ChimeraViewFrame(PDBEntry[] pe, SequenceI[][] seqs, AlignmentPanel ap) { - super(); + this(); openNewChimera(ap, pe, seqs); } - public ChimeraViewFrame(Map> toView, - AlignmentPanel alignPanel) + /** + * Default constructor + */ + public ChimeraViewFrame() { super(); /* - * Convert the map of sequences per pdb entry into the tied arrays expected - * by openNewChimera - * - * TODO pass the Map down to openNewChimera and its callees instead + * closeViewer will decide whether or not to close this frame + * depending on whether user chooses to Cancel or not */ - final Set pdbEntries = toView.keySet(); - PDBEntry[] pdbs = pdbEntries.toArray(new PDBEntry[pdbEntries.size()]); - SequenceI[][] seqsForPdbs = new SequenceI[pdbEntries.size()][]; - for (int i = 0; i < pdbs.length; i++) - { - final List seqsForPdb = toView.get(pdbs[i]); - seqsForPdbs[i] = seqsForPdb.toArray(new SequenceI[seqsForPdb.size()]); - } - - openNewChimera(alignPanel, pdbs, seqsForPdbs); + setDefaultCloseOperation(JInternalFrame.DO_NOTHING_ON_CLOSE); } /** - * add a new structure (with associated sequences and chains) to this viewer, - * retrieving it if necessary first. - * - * @param pdbentry - * @param seq - * @param chains - * @param alignFrame - * @param align - * if true, new structure(s) will be align using associated alignment + * Returns a list of any Chimera viewers in the desktop. The list is + * restricted to those linked to the given alignment panel if it is not null. */ - private void addStructure(final PDBEntry pdbentry, final SequenceI[] seq, - final String[] chains, final boolean b, - final IProgressIndicator alignFrame) - { - if (pdbentry.getFile() == null) - { - if (worker != null && worker.isAlive()) - { - // a retrieval is in progress, wait around and add ourselves to the - // queue. - new Thread(new Runnable() - { - public void run() - { - while (worker != null && worker.isAlive() && _started) - { - try - { - Thread.sleep(100 + ((int) Math.random() * 100)); - - } catch (Exception e) - { - } - - } - // and call ourselves again. - addStructure(pdbentry, seq, chains, b, alignFrame); - } - }).start(); - return; - } - } - // otherwise, start adding the structure. - jmb.addSequenceAndChain(new PDBEntry[] - { pdbentry }, new SequenceI[][] - { seq }, new String[][] - { chains }); - addingStructures = true; - _started = false; - alignAddedStructures = b; - // progressBar = alignFrame; // visual indication happens on caller frame. - (worker = new Thread(this)).start(); - return; - } - - private List getChimeraWindowsFor(AlignmentPanel apanel) + @Override + protected List getViewersFor(AlignmentPanel ap) { - List result = new ArrayList(); + List result = new ArrayList(); JInternalFrame[] frames = Desktop.instance.getAllFrames(); for (JInternalFrame frame : frames) { if (frame instanceof ChimeraViewFrame) { - if (((StructureViewerBase) frame).isLinkedWith(apanel)) + if (ap == null || ((StructureViewerBase) frame).isLinkedWith(ap)) { - result.add((ChimeraViewFrame) frame); + result.add((StructureViewerBase) frame); } } } @@ -595,11 +464,18 @@ public class ChimeraViewFrame extends StructureViewerBase */ void initChimera() { - jmb.setFinishedInit(false); - jalview.gui.Desktop.addInternalFrame(this, jmb.getViewerTitle("Chimera", true), + Desktop.addInternalFrame(this, jmb.getViewerTitle("Chimera", true), getBounds().width, getBounds().height); - jmb.launchChimera(); + if (!jmb.launchChimera()) + { + JvOptionPane.showMessageDialog(Desktop.desktop, + MessageManager.getString("label.chimera_failed"), + MessageManager.getString("label.error_loading_file"), + JvOptionPane.ERROR_MESSAGE); + this.dispose(); + return; + } if (this.chimeraSessionFile != null) { @@ -611,7 +487,6 @@ public class ChimeraViewFrame extends StructureViewerBase + chimeraSessionFile); } } - jmb.setFinishedInit(true); jmb.startChimeraListener(); } @@ -622,6 +497,7 @@ public class ChimeraViewFrame extends StructureViewerBase * * @param chainNames */ + @Override void setChainMenuItems(List chainNames) { chainMenu.removeAll(); @@ -633,6 +509,7 @@ public class ChimeraViewFrame extends StructureViewerBase MessageManager.getString("label.all")); menuItem.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent evt) { allChainsSelected = true; @@ -655,6 +532,7 @@ public class ChimeraViewFrame extends StructureViewerBase menuItem = new JCheckBoxMenuItem(chainName, true); menuItem.addItemListener(new ItemListener() { + @Override public void itemStateChanged(ItemEvent evt) { if (!allChainsSelected) @@ -671,6 +549,7 @@ public class ChimeraViewFrame extends StructureViewerBase /** * Show only the selected chain(s) in the viewer */ + @Override void showSelectedChains() { List toshow = new ArrayList(); @@ -696,20 +575,29 @@ public class ChimeraViewFrame extends StructureViewerBase * @param closeChimera * if true, close any linked Chimera process; if false, prompt first */ + @Override public void closeViewer(boolean closeChimera) { - if (jmb.isChimeraRunning()) + if (jmb != null && jmb.isChimeraRunning()) { if (!closeChimera) { String prompt = MessageManager.formatMessage( - "label.confirm_close_chimera", new Object[] - { jmb.getViewerTitle("Chimera", false) }); + "label.confirm_close_chimera", + new Object[] { jmb.getViewerTitle("Chimera", false) }); prompt = JvSwingUtils.wrapTooltip(true, prompt); - int confirm = JOptionPane.showConfirmDialog(this, prompt, + int confirm = JvOptionPane.showConfirmDialog(this, prompt, MessageManager.getString("label.close_viewer"), - JOptionPane.YES_NO_OPTION); - closeChimera = confirm == JOptionPane.YES_OPTION; + JvOptionPane.YES_NO_CANCEL_OPTION); + /* + * abort closure if user hits escape or Cancel + */ + if (confirm == JvOptionPane.CANCEL_OPTION + || confirm == JvOptionPane.CLOSED_OPTION) + { + return; + } + closeChimera = confirm == JvOptionPane.YES_OPTION; } jmb.closeViewer(closeChimera); } @@ -720,12 +608,14 @@ public class ChimeraViewFrame extends StructureViewerBase // TODO: check for memory leaks where instance isn't finalised because jmb // holds a reference to the window jmb = null; + dispose(); } /** * Open any newly added PDB structures in Chimera, having first fetched data * from PDB (if not already saved). */ + @Override public void run() { _started = true; @@ -735,6 +625,7 @@ public class ChimeraViewFrame extends StructureViewerBase List filePDB = new ArrayList(); List filePDBpos = new ArrayList(); PDBEntry thePdbEntry = null; + StructureFile pdb = null; try { String[] curfiles = jmb.getPdbFile(); // files currently in viewer @@ -795,16 +686,16 @@ public class ChimeraViewFrame extends StructureViewerBase if (errormsgs.length() > 0) { - JOptionPane.showInternalMessageDialog(Desktop.desktop, MessageManager + JvOptionPane.showInternalMessageDialog(Desktop.desktop, MessageManager .formatMessage("label.pdb_entries_couldnt_be_retrieved", - new Object[] - { errormsgs.toString() }), MessageManager - .getString("label.couldnt_load_file"), - JOptionPane.ERROR_MESSAGE); + new Object[] { errormsgs.toString() }), + MessageManager.getString("label.couldnt_load_file"), + JvOptionPane.ERROR_MESSAGE); } if (files.length() > 0) { + jmb.setFinishedInit(false); if (!addingStructures) { try @@ -825,16 +716,17 @@ public class ChimeraViewFrame extends StructureViewerBase { int pos = filePDBpos.get(num).intValue(); long startTime = startProgressBar("Chimera " - + MessageManager.getString("status.opening_file")); + + MessageManager.getString("status.opening_file_for") + + " " + pe.getId()); jmb.openFile(pe); jmb.addSequence(pos, jmb.getSequence()[pos]); File fl = new File(pe.getFile()); - String protocol = AppletFormatAdapter.URL; + DataSourceType protocol = DataSourceType.URL; try { if (fl.exists()) { - protocol = AppletFormatAdapter.FILE; + protocol = DataSourceType.FILE; } } catch (Throwable e) { @@ -843,10 +735,9 @@ public class ChimeraViewFrame extends StructureViewerBase stopProgressBar("", startTime); } // Explicitly map to the filename used by Chimera ; - jmb.getSsm().setMapping(jmb.getSequence()[pos], - jmb.getChains()[pos], - pe.getFile(), - protocol); + pdb = jmb.getSsm().setMapping(jmb.getSequence()[pos], + jmb.getChains()[pos], pe.getFile(), protocol); + stashFoundChains(pdb, pe.getFile()); } catch (OutOfMemoryError oomerror) { new OOMWarning( @@ -862,6 +753,8 @@ public class ChimeraViewFrame extends StructureViewerBase } } } + + jmb.refreshGUI(); jmb.setFinishedInit(true); jmb.setLoadingFromArchive(false); @@ -871,10 +764,11 @@ public class ChimeraViewFrame extends StructureViewerBase jmb.updateColours(ap); } // do superposition if asked to - if (alignAddedStructures) + if (Cache.getDefault("AUTOSUPERIMPOSE", true) && alignAddedStructures) { new Thread(new Runnable() { + @Override public void run() { alignStructs_withAllAlignPanels(); @@ -896,8 +790,20 @@ public class ChimeraViewFrame extends StructureViewerBase * @return * @throws Exception */ + + private void stashFoundChains(StructureFile pdb, String file) + { + for (int i = 0; i < pdb.getChains().size(); i++) + { + String chid = new String(pdb.getId() + ":" + + pdb.getChains().elementAt(i).id); + jmb.getChainNames().add(chid); + jmb.getChainFile().put(chid, file); + } + } private String fetchPdbFile(PDBEntry processingEntry) throws Exception { + // FIXME: this is duplicated code with Jmol frame ? String filePath = null; Pdb pdbclient = new Pdb(); AlignmentI pdbseq = null; @@ -909,8 +815,7 @@ public class ChimeraViewFrame extends StructureViewerBase * Write 'fetching PDB' progress on AlignFrame as we are not yet visible */ String msg = MessageManager.formatMessage("status.fetching_pdb", - new Object[] - { pdbid }); + new Object[] { pdbid }); getAlignmentPanel().alignFrame.setProgressBar(msg, handle); // long hdl = startProgressBar(MessageManager.formatMessage( // "status.fetching_pdb", new Object[] @@ -923,8 +828,7 @@ public class ChimeraViewFrame extends StructureViewerBase new OOMWarning("Retrieving PDB id " + pdbid, oomerror); } finally { - msg = pdbid + " " - + MessageManager.getString("label.state_completed"); + msg = pdbid + " " + MessageManager.getString("label.state_completed"); getAlignmentPanel().alignFrame.setProgressBar(msg, handle); // stopProgressBar(msg, hdl); } @@ -935,7 +839,7 @@ public class ChimeraViewFrame extends StructureViewerBase if (pdbseq != null && pdbseq.getHeight() > 0) { // just use the file name from the first sequence's first PDBEntry - filePath = new File(pdbseq.getSequenceAt(0).getPDBId() + filePath = new File(pdbseq.getSequenceAt(0).getAllPDBEntries() .elementAt(0).getFile()).getAbsolutePath(); processingEntry.setFile(filePath); } @@ -1208,10 +1112,10 @@ public class ChimeraViewFrame extends StructureViewerBase setChainMenuItems(jmb.getChainNames()); this.setTitle(jmb.getViewerTitle("Chimera", true)); - if (jmb.getPdbFile().length > 1 && jmb.getSequence().length > 1) - { + // if (jmb.getPdbFile().length > 1 && jmb.getSequence().length > 1) + // { viewerActionMenu.setVisible(true); - } + // } if (!jmb.isLoadingFromArchive()) { seqColour_actionPerformed(null); @@ -1269,6 +1173,7 @@ public class ChimeraViewFrame extends StructureViewerBase } } + @Override public void setJalviewColourScheme(ColourSchemeI ucs) { jmb.setJalviewColourScheme(ucs); @@ -1300,31 +1205,73 @@ public class ChimeraViewFrame extends StructureViewerBase } /** - * Ask Chimera to save its session to the designated file path. Returns true - * if successful, else false. + * Ask Chimera to save its session to the designated file path, or to a + * temporary file if the path is null. Returns the file path if successful, + * else null. * * @param filepath * @see getStateInfo */ - public boolean saveSession(String filepath) + protected String saveSession(String filepath) { - boolean result = jmb.saveSession(filepath); - if (result) + String pathUsed = filepath; + try + { + if (pathUsed == null) + { + File tempFile = File.createTempFile("chimera", ".py"); + tempFile.deleteOnExit(); + pathUsed = tempFile.getPath(); + } + boolean result = jmb.saveSession(pathUsed); + if (result) + { + this.chimeraSessionFile = pathUsed; + return pathUsed; + } + } catch (IOException e) { - this.chimeraSessionFile = filepath; } - return result; + return null; } /** - * Returns the file path of the Chimera session file the last time it was - * saved. If it was never saved, returns an empty string. There is no - * guarantee that the Chimera session has not changed since it was saved. + * Returns a string representing the state of the Chimera session. This is + * done by requesting Chimera to save its session to a temporary file, then + * reading the file contents. Returns an empty string on any error. */ @Override public String getStateInfo() { - return this.chimeraSessionFile == null ? "" : chimeraSessionFile; + String sessionFile = saveSession(null); + if (sessionFile == null) + { + return ""; + } + InputStream is = null; + try + { + File f = new File(sessionFile); + byte[] bytes = new byte[(int) f.length()]; + is = new FileInputStream(sessionFile); + is.read(bytes); + return new String(bytes); + } catch (IOException e) + { + return ""; + } finally + { + if (is != null) + { + try + { + is.close(); + } catch (IOException e) + { + // ignore + } + } + } } @Override @@ -1332,4 +1279,16 @@ public class ChimeraViewFrame extends StructureViewerBase { jmb.focusView(); } + + @Override + public ViewerType getViewerType() + { + return ViewerType.CHIMERA; + } + + @Override + protected AAStructureBindingModel getBindingModel() + { + return jmb; + } }