Clover icon

jalviewX

  1. Project Clover database Wed Oct 31 2018 15:13:58 GMT
  2. Package jalview.gui

File ChimeraViewFrame.java

 

Coverage histogram

../../img/srcFileCovDistChart0.png
56% of files have more coverage

Code metrics

76
235
33
1
843
591
86
0.37
7.12
33
2.61

Classes

Class Line # Actions
ChimeraViewFrame 66 235 86 344
0.00%
 

Contributing tests

No tests hitting this source file were found.

Source view

1    /*
2    * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3    * Copyright (C) $$Year-Rel$$ The Jalview Authors
4    *
5    * This file is part of Jalview.
6    *
7    * Jalview is free software: you can redistribute it and/or
8    * modify it under the terms of the GNU General Public License
9    * as published by the Free Software Foundation, either version 3
10    * of the License, or (at your option) any later version.
11    *
12    * Jalview is distributed in the hope that it will be useful, but
13    * WITHOUT ANY WARRANTY; without even the implied warranty
14    * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15    * PURPOSE. See the GNU General Public License for more details.
16    *
17    * You should have received a copy of the GNU General Public License
18    * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19    * The Jalview Authors are detailed in the 'AUTHORS' file.
20    */
21    package jalview.gui;
22   
23    import jalview.api.FeatureRenderer;
24    import jalview.bin.Cache;
25    import jalview.datamodel.AlignmentI;
26    import jalview.datamodel.PDBEntry;
27    import jalview.datamodel.SequenceI;
28    import jalview.ext.rbvi.chimera.ChimeraCommands;
29    import jalview.ext.rbvi.chimera.JalviewChimeraBinding;
30    import jalview.gui.StructureViewer.ViewerType;
31    import jalview.io.DataSourceType;
32    import jalview.io.StructureFile;
33    import jalview.structures.models.AAStructureBindingModel;
34    import jalview.util.BrowserLauncher;
35    import jalview.util.ImageMaker.TYPE;
36    import jalview.util.MessageManager;
37    import jalview.util.Platform;
38    import jalview.ws.dbsources.Pdb;
39   
40    import java.awt.event.ActionEvent;
41    import java.awt.event.ActionListener;
42    import java.awt.event.MouseAdapter;
43    import java.awt.event.MouseEvent;
44    import java.io.File;
45    import java.io.FileInputStream;
46    import java.io.IOException;
47    import java.io.InputStream;
48    import java.util.ArrayList;
49    import java.util.Collections;
50    import java.util.List;
51    import java.util.Random;
52   
53    import javax.swing.JCheckBoxMenuItem;
54    import javax.swing.JInternalFrame;
55    import javax.swing.JMenu;
56    import javax.swing.JMenuItem;
57    import javax.swing.event.InternalFrameAdapter;
58    import javax.swing.event.InternalFrameEvent;
59   
60    /**
61    * GUI elements for handling an external chimera display
62    *
63    * @author jprocter
64    *
65    */
 
66    public class ChimeraViewFrame extends StructureViewerBase
67    {
68    private JalviewChimeraBinding jmb;
69   
70    private IProgressIndicator progressBar = null;
71   
72    /*
73    * Path to Chimera session file. This is set when an open Jalview/Chimera
74    * session is saved, or on restore from a Jalview project (if it holds the
75    * filename of any saved Chimera sessions).
76    */
77    private String chimeraSessionFile = null;
78   
79    private Random random = new Random();
80   
81    private int myWidth = 500;
82   
83    private int myHeight = 150;
84   
85    /**
86    * Initialise menu options.
87    */
 
88  0 toggle @Override
89    protected void initMenus()
90    {
91  0 super.initMenus();
92   
93  0 viewerActionMenu.setText(MessageManager.getString("label.chimera"));
94   
95  0 viewerColour
96    .setText(MessageManager.getString("label.colour_with_chimera"));
97  0 viewerColour.setToolTipText(MessageManager
98    .getString("label.let_chimera_manage_structure_colours"));
99   
100  0 helpItem.setText(MessageManager.getString("label.chimera_help"));
101  0 savemenu.setVisible(false); // not yet implemented
102  0 viewMenu.add(fitToWindow);
103   
104  0 JMenuItem writeFeatures = new JMenuItem(
105    MessageManager.getString("label.create_chimera_attributes"));
106  0 writeFeatures.setToolTipText(MessageManager
107    .getString("label.create_chimera_attributes_tip"));
108  0 writeFeatures.addActionListener(new ActionListener()
109    {
 
110  0 toggle @Override
111    public void actionPerformed(ActionEvent e)
112    {
113  0 sendFeaturesToChimera();
114    }
115    });
116  0 viewerActionMenu.add(writeFeatures);
117   
118  0 final JMenu fetchAttributes = new JMenu(
119    MessageManager.getString("label.fetch_chimera_attributes"));
120  0 fetchAttributes.setToolTipText(
121    MessageManager.getString("label.fetch_chimera_attributes_tip"));
122  0 fetchAttributes.addMouseListener(new MouseAdapter()
123    {
124   
 
125  0 toggle @Override
126    public void mouseEntered(MouseEvent e)
127    {
128  0 buildAttributesMenu(fetchAttributes);
129    }
130    });
131  0 viewerActionMenu.add(fetchAttributes);
132    }
133   
134    /**
135    * Query Chimera for its residue attribute names and add them as items off the
136    * attributes menu
137    *
138    * @param attributesMenu
139    */
 
140  0 toggle protected void buildAttributesMenu(JMenu attributesMenu)
141    {
142  0 List<String> atts = jmb.sendChimeraCommand("list resattr", true);
143  0 if (atts == null)
144    {
145  0 return;
146    }
147  0 attributesMenu.removeAll();
148  0 Collections.sort(atts);
149  0 for (String att : atts)
150    {
151  0 final String attName = att.split(" ")[1];
152   
153    /*
154    * ignore 'jv_*' attributes, as these are Jalview features that have
155    * been transferred to residue attributes in Chimera!
156    */
157  0 if (!attName.startsWith(ChimeraCommands.NAMESPACE_PREFIX))
158    {
159  0 JMenuItem menuItem = new JMenuItem(attName);
160  0 menuItem.addActionListener(new ActionListener()
161    {
 
162  0 toggle @Override
163    public void actionPerformed(ActionEvent e)
164    {
165  0 getChimeraAttributes(attName);
166    }
167    });
168  0 attributesMenu.add(menuItem);
169    }
170    }
171    }
172   
173    /**
174    * Read residues in Chimera with the given attribute name, and set as features
175    * on the corresponding sequence positions (if any)
176    *
177    * @param attName
178    */
 
179  0 toggle protected void getChimeraAttributes(String attName)
180    {
181  0 jmb.copyStructureAttributesToFeatures(attName, getAlignmentPanel());
182    }
183   
184    /**
185    * Send a command to Chimera to create residue attributes for Jalview features
186    * <p>
187    * The syntax is: setattr r <attName> <attValue> <atomSpec>
188    * <p>
189    * For example: setattr r jv:chain "Ferredoxin-1, Chloroplastic" #0:94.A
190    */
 
191  0 toggle protected void sendFeaturesToChimera()
192    {
193  0 int count = jmb.sendFeaturesToViewer(getAlignmentPanel());
194  0 statusBar.setText(
195    MessageManager.formatMessage("label.attributes_set", count));
196    }
197   
198    /**
199    * open a single PDB structure in a new Chimera view
200    *
201    * @param pdbentry
202    * @param seq
203    * @param chains
204    * @param ap
205    */
 
206  0 toggle public ChimeraViewFrame(PDBEntry pdbentry, SequenceI[] seq,
207    String[] chains, final AlignmentPanel ap)
208    {
209  0 this();
210   
211  0 openNewChimera(ap, new PDBEntry[] { pdbentry },
212    new SequenceI[][]
213    { seq });
214    }
215   
216    /**
217    * Create a helper to manage progress bar display
218    */
 
219  0 toggle protected void createProgressBar()
220    {
221  0 if (progressBar == null)
222    {
223  0 progressBar = new ProgressBar(statusPanel, statusBar);
224    }
225    }
226   
 
227  0 toggle private void openNewChimera(AlignmentPanel ap, PDBEntry[] pdbentrys,
228    SequenceI[][] seqs)
229    {
230  0 createProgressBar();
231  0 jmb = new JalviewChimeraBindingModel(this,
232    ap.getStructureSelectionManager(), pdbentrys, seqs, null);
233  0 addAlignmentPanel(ap);
234  0 useAlignmentPanelForColourbyseq(ap);
235   
236  0 if (pdbentrys.length > 1)
237    {
238  0 useAlignmentPanelForSuperposition(ap);
239    }
240  0 jmb.setColourBySequence(true);
241  0 setSize(myWidth, myHeight);
242  0 initMenus();
243   
244  0 addingStructures = false;
245  0 worker = new Thread(this);
246  0 worker.start();
247   
248  0 this.addInternalFrameListener(new InternalFrameAdapter()
249    {
 
250  0 toggle @Override
251    public void internalFrameClosing(
252    InternalFrameEvent internalFrameEvent)
253    {
254  0 closeViewer(false);
255    }
256    });
257   
258    }
259   
260    /**
261    * Create a new viewer from saved session state data including Chimera session
262    * file
263    *
264    * @param chimeraSessionFile
265    * @param alignPanel
266    * @param pdbArray
267    * @param seqsArray
268    * @param colourByChimera
269    * @param colourBySequence
270    * @param newViewId
271    */
 
272  0 toggle public ChimeraViewFrame(String chimeraSessionFile,
273    AlignmentPanel alignPanel, PDBEntry[] pdbArray,
274    SequenceI[][] seqsArray, boolean colourByChimera,
275    boolean colourBySequence, String newViewId)
276    {
277  0 this();
278  0 setViewId(newViewId);
279  0 this.chimeraSessionFile = chimeraSessionFile;
280  0 openNewChimera(alignPanel, pdbArray, seqsArray);
281  0 if (colourByChimera)
282    {
283  0 jmb.setColourBySequence(false);
284  0 seqColour.setSelected(false);
285  0 viewerColour.setSelected(true);
286    }
287  0 else if (colourBySequence)
288    {
289  0 jmb.setColourBySequence(true);
290  0 seqColour.setSelected(true);
291  0 viewerColour.setSelected(false);
292    }
293    }
294   
295    /**
296    * create a new viewer containing several structures, optionally superimposed
297    * using the given alignPanel.
298    *
299    * @param pe
300    * @param seqs
301    * @param ap
302    */
 
303  0 toggle public ChimeraViewFrame(PDBEntry[] pe, boolean alignAdded,
304    SequenceI[][] seqs,
305    AlignmentPanel ap)
306    {
307  0 this();
308  0 setAlignAddedStructures(alignAdded);
309  0 openNewChimera(ap, pe, seqs);
310    }
311   
312    /**
313    * Default constructor
314    */
 
315  0 toggle public ChimeraViewFrame()
316    {
317  0 super();
318   
319    /*
320    * closeViewer will decide whether or not to close this frame
321    * depending on whether user chooses to Cancel or not
322    */
323  0 setDefaultCloseOperation(JInternalFrame.DO_NOTHING_ON_CLOSE);
324    }
325   
326    /**
327    * Launch Chimera. If we have a chimera session file name, send Chimera the
328    * command to open its saved session file.
329    */
 
330  0 toggle void initChimera()
331    {
332  0 jmb.setFinishedInit(false);
333  0 Desktop.addInternalFrame(this,
334    jmb.getViewerTitle(getViewerName(), true), getBounds().width,
335    getBounds().height);
336   
337  0 if (!jmb.launchChimera())
338    {
339  0 JvOptionPane.showMessageDialog(Desktop.desktop,
340    MessageManager.getString("label.chimera_failed"),
341    MessageManager.getString("label.error_loading_file"),
342    JvOptionPane.ERROR_MESSAGE);
343  0 this.dispose();
344  0 return;
345    }
346   
347  0 if (this.chimeraSessionFile != null)
348    {
349  0 boolean opened = jmb.openSession(chimeraSessionFile);
350  0 if (!opened)
351    {
352  0 System.err.println("An error occurred opening Chimera session file "
353    + chimeraSessionFile);
354    }
355    }
356   
357  0 jmb.startChimeraListener();
358    }
359   
360    /**
361    * Show only the selected chain(s) in the viewer
362    */
 
363  0 toggle @Override
364    void showSelectedChains()
365    {
366  0 List<String> toshow = new ArrayList<>();
367  0 for (int i = 0; i < chainMenu.getItemCount(); i++)
368    {
369  0 if (chainMenu.getItem(i) instanceof JCheckBoxMenuItem)
370    {
371  0 JCheckBoxMenuItem item = (JCheckBoxMenuItem) chainMenu.getItem(i);
372  0 if (item.isSelected())
373    {
374  0 toshow.add(item.getText());
375    }
376    }
377    }
378  0 jmb.showChains(toshow);
379    }
380   
381    /**
382    * Close down this instance of Jalview's Chimera viewer, giving the user the
383    * option to close the associated Chimera window (process). They may wish to
384    * keep it open until they have had an opportunity to save any work.
385    *
386    * @param closeChimera
387    * if true, close any linked Chimera process; if false, prompt first
388    */
 
389  0 toggle @Override
390    public void closeViewer(boolean closeChimera)
391    {
392  0 if (jmb != null && jmb.isChimeraRunning())
393    {
394  0 if (!closeChimera)
395    {
396  0 String prompt = MessageManager
397    .formatMessage("label.confirm_close_chimera", new Object[]
398    { jmb.getViewerTitle(getViewerName(), false) });
399  0 prompt = JvSwingUtils.wrapTooltip(true, prompt);
400  0 int confirm = JvOptionPane.showConfirmDialog(this, prompt,
401    MessageManager.getString("label.close_viewer"),
402    JvOptionPane.YES_NO_CANCEL_OPTION);
403    /*
404    * abort closure if user hits escape or Cancel
405    */
406  0 if (confirm == JvOptionPane.CANCEL_OPTION
407    || confirm == JvOptionPane.CLOSED_OPTION)
408    {
409  0 return;
410    }
411  0 closeChimera = confirm == JvOptionPane.YES_OPTION;
412    }
413  0 jmb.closeViewer(closeChimera);
414    }
415  0 setAlignmentPanel(null);
416  0 _aps.clear();
417  0 _alignwith.clear();
418  0 _colourwith.clear();
419    // TODO: check for memory leaks where instance isn't finalised because jmb
420    // holds a reference to the window
421  0 jmb = null;
422  0 dispose();
423    }
424   
425    /**
426    * Open any newly added PDB structures in Chimera, having first fetched data
427    * from PDB (if not already saved).
428    */
 
429  0 toggle @Override
430    public void run()
431    {
432  0 _started = true;
433    // todo - record which pdbids were successfully imported.
434  0 StringBuilder errormsgs = new StringBuilder(128);
435  0 StringBuilder files = new StringBuilder(128);
436  0 List<PDBEntry> filePDB = new ArrayList<>();
437  0 List<Integer> filePDBpos = new ArrayList<>();
438  0 PDBEntry thePdbEntry = null;
439  0 StructureFile pdb = null;
440  0 try
441    {
442  0 String[] curfiles = jmb.getStructureFiles(); // files currently in viewer
443    // TODO: replace with reference fetching/transfer code (validate PDBentry
444    // as a DBRef?)
445  0 for (int pi = 0; pi < jmb.getPdbCount(); pi++)
446    {
447  0 String file = null;
448  0 thePdbEntry = jmb.getPdbEntry(pi);
449  0 if (thePdbEntry.getFile() == null)
450    {
451    /*
452    * Retrieve PDB data, save to file, attach to PDBEntry
453    */
454  0 file = fetchPdbFile(thePdbEntry);
455  0 if (file == null)
456    {
457  0 errormsgs.append("'" + thePdbEntry.getId() + "' ");
458    }
459    }
460    else
461    {
462    /*
463    * Got file already - ignore if already loaded in Chimera.
464    */
465  0 file = new File(thePdbEntry.getFile()).getAbsoluteFile()
466    .getPath();
467  0 if (curfiles != null && curfiles.length > 0)
468    {
469  0 addingStructures = true; // already files loaded.
470  0 for (int c = 0; c < curfiles.length; c++)
471    {
472  0 if (curfiles[c].equals(file))
473    {
474  0 file = null;
475  0 break;
476    }
477    }
478    }
479    }
480  0 if (file != null)
481    {
482  0 filePDB.add(thePdbEntry);
483  0 filePDBpos.add(Integer.valueOf(pi));
484  0 files.append(" \"" + Platform.escapeString(file) + "\"");
485    }
486    }
487    } catch (OutOfMemoryError oomerror)
488    {
489  0 new OOMWarning("Retrieving PDB files: " + thePdbEntry.getId(),
490    oomerror);
491    } catch (Exception ex)
492    {
493  0 ex.printStackTrace();
494  0 errormsgs.append(
495    "When retrieving pdbfiles for '" + thePdbEntry.getId() + "'");
496    }
497  0 if (errormsgs.length() > 0)
498    {
499   
500  0 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
501    MessageManager.formatMessage(
502    "label.pdb_entries_couldnt_be_retrieved", new Object[]
503    { errormsgs.toString() }),
504    MessageManager.getString("label.couldnt_load_file"),
505    JvOptionPane.ERROR_MESSAGE);
506    }
507   
508  0 if (files.length() > 0)
509    {
510  0 jmb.setFinishedInit(false);
511  0 if (!addingStructures)
512    {
513  0 try
514    {
515  0 initChimera();
516    } catch (Exception ex)
517    {
518  0 Cache.log.error("Couldn't open Chimera viewer!", ex);
519    }
520    }
521  0 int num = -1;
522  0 for (PDBEntry pe : filePDB)
523    {
524  0 num++;
525  0 if (pe.getFile() != null)
526    {
527  0 try
528    {
529  0 int pos = filePDBpos.get(num).intValue();
530  0 long startTime = startProgressBar(getViewerName() + " "
531    + MessageManager.getString("status.opening_file_for")
532    + " " + pe.getId());
533  0 jmb.openFile(pe);
534  0 jmb.addSequence(pos, jmb.getSequence()[pos]);
535  0 File fl = new File(pe.getFile());
536  0 DataSourceType protocol = DataSourceType.URL;
537  0 try
538    {
539  0 if (fl.exists())
540    {
541  0 protocol = DataSourceType.FILE;
542    }
543    } catch (Throwable e)
544    {
545    } finally
546    {
547  0 stopProgressBar("", startTime);
548    }
549    // Explicitly map to the filename used by Chimera ;
550   
551  0 pdb = jmb.getSsm().setMapping(jmb.getSequence()[pos],
552    jmb.getChains()[pos], pe.getFile(), protocol,
553    progressBar);
554  0 stashFoundChains(pdb, pe.getFile());
555   
556    } catch (OutOfMemoryError oomerror)
557    {
558  0 new OOMWarning(
559    "When trying to open and map structures from Chimera!",
560    oomerror);
561    } catch (Exception ex)
562    {
563  0 Cache.log.error(
564    "Couldn't open " + pe.getFile() + " in Chimera viewer!",
565    ex);
566    } finally
567    {
568  0 Cache.log.debug("File locations are " + files);
569    }
570    }
571    }
572   
573  0 jmb.refreshGUI();
574  0 jmb.setFinishedInit(true);
575  0 jmb.setLoadingFromArchive(false);
576   
577    /*
578    * ensure that any newly discovered features (e.g. RESNUM)
579    * are added to any open feature settings dialog
580    */
581  0 FeatureRenderer fr = getBinding().getFeatureRenderer(null);
582  0 if (fr != null)
583    {
584  0 fr.featuresAdded();
585    }
586   
587    // refresh the sequence colours for the new structure(s)
588  0 for (AlignmentPanel ap : _colourwith)
589    {
590  0 jmb.updateColours(ap);
591    }
592    // do superposition if asked to
593  0 if (alignAddedStructures)
594    {
595  0 new Thread(new Runnable()
596    {
 
597  0 toggle @Override
598    public void run()
599    {
600  0 alignStructs_withAllAlignPanels();
601    }
602    }).start();
603    }
604  0 addingStructures = false;
605    }
606  0 _started = false;
607  0 worker = null;
608    }
609   
610    /**
611    * Fetch PDB data and save to a local file. Returns the full path to the file,
612    * or null if fetch fails. TODO: refactor to common with Jmol ? duplication
613    *
614    * @param processingEntry
615    * @return
616    * @throws Exception
617    */
618   
 
619  0 toggle private void stashFoundChains(StructureFile pdb, String file)
620    {
621  0 for (int i = 0; i < pdb.getChains().size(); i++)
622    {
623  0 String chid = new String(
624    pdb.getId() + ":" + pdb.getChains().elementAt(i).id);
625  0 jmb.getChainNames().add(chid);
626  0 jmb.getChainFile().put(chid, file);
627    }
628    }
629   
 
630  0 toggle private String fetchPdbFile(PDBEntry processingEntry) throws Exception
631    {
632  0 String filePath = null;
633  0 Pdb pdbclient = new Pdb();
634  0 AlignmentI pdbseq = null;
635  0 String pdbid = processingEntry.getId();
636  0 long handle = System.currentTimeMillis()
637    + Thread.currentThread().hashCode();
638   
639    /*
640    * Write 'fetching PDB' progress on AlignFrame as we are not yet visible
641    */
642  0 String msg = MessageManager.formatMessage("status.fetching_pdb",
643    new Object[]
644    { pdbid });
645  0 getAlignmentPanel().alignFrame.setProgressBar(msg, handle);
646    // long hdl = startProgressBar(MessageManager.formatMessage(
647    // "status.fetching_pdb", new Object[]
648    // { pdbid }));
649  0 try
650    {
651  0 pdbseq = pdbclient.getSequenceRecords(pdbid);
652    } catch (OutOfMemoryError oomerror)
653    {
654  0 new OOMWarning("Retrieving PDB id " + pdbid, oomerror);
655    } finally
656    {
657  0 msg = pdbid + " " + MessageManager.getString("label.state_completed");
658  0 getAlignmentPanel().alignFrame.setProgressBar(msg, handle);
659    // stopProgressBar(msg, hdl);
660    }
661    /*
662    * If PDB data were saved and are not invalid (empty alignment), return the
663    * file path.
664    */
665  0 if (pdbseq != null && pdbseq.getHeight() > 0)
666    {
667    // just use the file name from the first sequence's first PDBEntry
668  0 filePath = new File(pdbseq.getSequenceAt(0).getAllPDBEntries()
669    .elementAt(0).getFile()).getAbsolutePath();
670  0 processingEntry.setFile(filePath);
671    }
672  0 return filePath;
673    }
674   
675    /**
676    * Convenience method to update the progress bar if there is one. Be sure to
677    * call stopProgressBar with the returned handle to remove the message.
678    *
679    * @param msg
680    * @param handle
681    */
 
682  0 toggle public long startProgressBar(String msg)
683    {
684    // TODO would rather have startProgress/stopProgress as the
685    // IProgressIndicator interface
686  0 long tm = random.nextLong();
687  0 if (progressBar != null)
688    {
689  0 progressBar.setProgressBar(msg, tm);
690    }
691  0 return tm;
692    }
693   
694    /**
695    * End the progress bar with the specified handle, leaving a message (if not
696    * null) on the status bar
697    *
698    * @param msg
699    * @param handle
700    */
 
701  0 toggle public void stopProgressBar(String msg, long handle)
702    {
703  0 if (progressBar != null)
704    {
705  0 progressBar.setProgressBar(msg, handle);
706    }
707    }
708   
 
709  0 toggle @Override
710    public void makePDBImage(TYPE imageType)
711    {
712  0 throw new UnsupportedOperationException(
713    "Image export for Chimera is not implemented");
714    }
715   
 
716  0 toggle @Override
717    public void showHelp_actionPerformed(ActionEvent actionEvent)
718    {
719  0 try
720    {
721  0 BrowserLauncher
722    .openURL("https://www.cgl.ucsf.edu/chimera/docs/UsersGuide");
723    } catch (IOException ex)
724    {
725    }
726    }
727   
 
728  0 toggle @Override
729    public AAStructureBindingModel getBinding()
730    {
731  0 return jmb;
732    }
733   
734    /**
735    * Ask Chimera to save its session to the designated file path, or to a
736    * temporary file if the path is null. Returns the file path if successful,
737    * else null.
738    *
739    * @param filepath
740    * @see getStateInfo
741    */
 
742  0 toggle protected String saveSession(String filepath)
743    {
744  0 String pathUsed = filepath;
745  0 try
746    {
747  0 if (pathUsed == null)
748    {
749  0 File tempFile = File.createTempFile("chimera", ".py");
750  0 tempFile.deleteOnExit();
751  0 pathUsed = tempFile.getPath();
752    }
753  0 boolean result = jmb.saveSession(pathUsed);
754  0 if (result)
755    {
756  0 this.chimeraSessionFile = pathUsed;
757  0 return pathUsed;
758    }
759    } catch (IOException e)
760    {
761    }
762  0 return null;
763    }
764   
765    /**
766    * Returns a string representing the state of the Chimera session. This is
767    * done by requesting Chimera to save its session to a temporary file, then
768    * reading the file contents. Returns an empty string on any error.
769    */
 
770  0 toggle @Override
771    public String getStateInfo()
772    {
773  0 String sessionFile = saveSession(null);
774  0 if (sessionFile == null)
775    {
776  0 return "";
777    }
778  0 InputStream is = null;
779  0 try
780    {
781  0 File f = new File(sessionFile);
782  0 byte[] bytes = new byte[(int) f.length()];
783  0 is = new FileInputStream(sessionFile);
784  0 is.read(bytes);
785  0 return new String(bytes);
786    } catch (IOException e)
787    {
788  0 return "";
789    } finally
790    {
791  0 if (is != null)
792    {
793  0 try
794    {
795  0 is.close();
796    } catch (IOException e)
797    {
798    // ignore
799    }
800    }
801    }
802    }
803   
 
804  0 toggle @Override
805    protected void fitToWindow_actionPerformed()
806    {
807  0 jmb.focusView();
808    }
809   
 
810  0 toggle @Override
811    public ViewerType getViewerType()
812    {
813  0 return ViewerType.CHIMERA;
814    }
815   
 
816  0 toggle @Override
817    protected String getViewerName()
818    {
819  0 return "Chimera";
820    }
821   
822    /**
823    * Sends commands to align structures according to associated alignment(s).
824    *
825    * @return
826    */
 
827  0 toggle @Override
828    protected String alignStructs_withAllAlignPanels()
829    {
830  0 String reply = super.alignStructs_withAllAlignPanels();
831  0 if (reply != null)
832    {
833  0 statusBar.setText("Superposition failed: " + reply);
834    }
835  0 return reply;
836    }
837   
 
838  0 toggle @Override
839    protected IProgressIndicator getIProgressIndicator()
840    {
841  0 return progressBar;
842    }
843    }