import jalview.datamodel.PDBEntry;
import jalview.datamodel.SequenceI;
import jalview.ext.rbvi.chimera.JalviewChimeraBinding;
+import jalview.gui.Jalview2XML.ViewerData;
import jalview.io.AppletFormatAdapter;
import jalview.io.JalviewFileChooser;
import jalview.io.JalviewFileView;
*/
private Thread worker = null;
+ /*
+ * Path to Chimera session file - set in saveSession()
+ */
+ private String chimeraSessionFile = "";
+
/**
* Initialise menu options.
*/
openNewChimera(ap, pe, seqs);
}
- public AlignmentPanel[] getAllAlignmentPanels()
- {
- AlignmentPanel[] t, list = new AlignmentPanel[0];
- for (String setid : _aps)
- {
- AlignmentPanel[] panels = PaintRefresher.getAssociatedPanels(setid);
- if (panels != null)
- {
- t = new AlignmentPanel[list.length + panels.length];
- System.arraycopy(list, 0, t, 0, list.length);
- System.arraycopy(panels, 0, t, list.length, panels.length);
- list = t;
- }
- }
-
- return list;
- }
-
- /**
- * set the primary alignmentPanel reference and add another alignPanel to the
- * list of ones to use for colouring and aligning
- *
- * @param nap
- */
- public void addAlignmentPanel(AlignmentPanel nap)
- {
- if (getAlignmentPanel() == null)
- {
- setAlignmentPanel(nap);
- }
- if (!_aps.contains(nap.av.getSequenceSetId()))
- {
- _aps.add(nap.av.getSequenceSetId());
- }
- }
-
/**
- * remove any references held to the given alignment panel
+ * Create a new viewer from saved session state data.
*
- * @param nap
+ * @param viewerData
+ * @param af
*/
- public void removeAlignmentPanel(AlignmentPanel nap)
- {
- try
- {
- _alignwith.remove(nap);
- _colourwith.remove(nap);
- if (getAlignmentPanel() == nap)
- {
- setAlignmentPanel(null);
- for (AlignmentPanel aps : getAllAlignmentPanels())
- {
- if (aps != nap)
- {
- setAlignmentPanel(aps);
- break;
- }
- }
- }
- } catch (Exception ex)
- {
- }
- if (getAlignmentPanel() != null)
- {
- buildActionMenu();
- }
- }
-
- public void useAlignmentPanelForSuperposition(AlignmentPanel nap)
- {
- addAlignmentPanel(nap);
- if (!_alignwith.contains(nap))
- {
- _alignwith.add(nap);
- }
- }
-
- public void excludeAlignmentPanelForSuperposition(AlignmentPanel nap)
- {
- if (_alignwith.contains(nap))
- {
- _alignwith.remove(nap);
- }
- }
-
- public void useAlignmentPanelForColourbyseq(AlignmentPanel nap,
- boolean enableColourBySeq)
- {
- useAlignmentPanelForColourbyseq(nap);
- getBinding().setColourBySequence(enableColourBySeq);
- seqColour.setSelected(enableColourBySeq);
- viewerColour.setSelected(!enableColourBySeq);
- }
-
- public void useAlignmentPanelForColourbyseq(AlignmentPanel nap)
+ public ChimeraViewFrame(ViewerData viewerData, AlignFrame af)
{
- addAlignmentPanel(nap);
- if (!_colourwith.contains(nap))
- {
- _colourwith.add(nap);
- }
- }
-
- public void excludeAlignmentPanelForColourbyseq(AlignmentPanel nap)
- {
- if (_colourwith.contains(nap))
- {
- _colourwith.remove(nap);
- }
+ super();
+ String chimeraSessionFile = viewerData.stateData;
+ openNewChimera(af.alignPanel, new PDBEntry[]
+ {}, new SequenceI[][]
+ {});
+ initChimera("open " + chimeraSessionFile);
+ // TODO restore mappings
}
/**
* if successful, else false.
*
* @param filepath
+ * @see getStateInfo
*/
public boolean saveSession(String filepath)
{
- return jmb.saveSession(filepath);
+ boolean result = jmb.saveSession(filepath);
+ if (result)
+ {
+ this.chimeraSessionFile = filepath;
+ }
+ return result;
+ }
+
+ /**
+ * 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.
+ */
+ @Override
+ public String getStateInfo()
+ {
+ return this.chimeraSessionFile;
}
}
public class Jalview2XML
{
- private class ViewerData
+ /**
+ * A data bean to hold stored data about a structure viewer.
+ */
+ public class ViewerData
{
private int x;
private int height;
- private boolean alignWithPanel;
+ public boolean alignWithPanel;
- private boolean colourWithAlignPanel;
+ public boolean colourWithAlignPanel;
- private boolean colourByViewer;
+ public boolean colourByViewer;
- private String stateData = "";
+ String stateData = "";
// todo: java bean in place of Object []
private Map<File, Object[]> fileData = new HashMap<File, Object[]>();
boolean storeDS, JarOutputStream jout)
{
initSeqRefs();
+ List<String> viewIds = new ArrayList<String>();
List<UserColourScheme> userColours = new ArrayList<UserColourScheme>();
AlignViewport av = ap.av;
pdb.setType(entry.getType());
/*
- * Store any JMol or Chimera views associated with this sequence. This
+ * Store any structure views associated with this sequence. This
* section copes with duplicate entries in the project, so a dataset
* only view *should* be coped with sensibly.
*/
- List<String> viewIds = new ArrayList<String>();
// This must have been loaded, is it still visible?
JInternalFrame[] frames = Desktop.desktop.getAllFrames();
String matchedFile = null;
}
}
}
+ // Instantiate the associated structure views
+ for (Entry<String, ViewerData> entry : jmolViewIds.entrySet())
+ {
+ createOrLinkStructureViewer(entry, af, ap);
+ }
+ }
+
+ /**
+ *
+ * @param viewerData
+ * @param af
+ * @param ap
+ */
+ protected void createOrLinkStructureViewer(
+ Entry<String, ViewerData> viewerData, AlignFrame af,
+ AlignmentPanel ap)
+ {
+ final ViewerData svattrib = viewerData.getValue();
+
+ /*
+ * Search for any viewer windows already open from other alignment views
+ * that exactly match the stored structure state
+ */
+ StructureViewerBase comp = findMatchingViewer(viewerData);
+
+ if (comp != null)
{
+ linkStructureViewer(ap, comp, svattrib);
+ return;
+ }
- // Instantiate the associated Jmol views
- for (Entry<String, ViewerData> entry : jmolViewIds.entrySet())
+ /*
+ * Pending an XML element for ViewerType, just check if stateData contains
+ * "chimera" (part of the chimera session filename).
+ */
+ if (svattrib.stateData.indexOf("chimera") > -1)
+ {
+ createChimeraViewer(viewerData, af);
+ }
+ else
+ {
+ createJmolViewer(viewerData, af);
+ }
+ }
+
+ /**
+ * Create a new Chimera viewer.
+ *
+ * @param viewerData
+ * @param af
+ */
+ protected void createChimeraViewer(Entry<String, ViewerData> viewerData,
+ AlignFrame af)
+ {
+ final ViewerData svattrib = viewerData.getValue();
+ ChimeraViewFrame cvf = new ChimeraViewFrame(svattrib, af);
+ }
+
+ /**
+ * Create a new Jmol window. First parse the Jmol state to translate filenames
+ * loaded into the view, and record the order in which files are shown in the
+ * Jmol view, so we can add the sequence mappings in same order.
+ *
+ * @param viewerData
+ * @param af
+ */
+ protected void createJmolViewer(
+ final Entry<String, ViewerData> viewerData, AlignFrame af)
+ {
+ final ViewerData svattrib = viewerData.getValue();
+ String state = svattrib.stateData;
+ List<String> pdbfilenames = new ArrayList<String>();
+ List<SequenceI[]> seqmaps = new ArrayList<SequenceI[]>();
+ List<String> pdbids = new ArrayList<String>();
+ StringBuilder newFileLoc = new StringBuilder(64);
+ int cp = 0, ncp, ecp;
+ Map<File, Object[]> oldFiles = svattrib.fileData;
+ while ((ncp = state.indexOf("load ", cp)) > -1)
+ {
+ do
+ {
+ // look for next filename in load statement
+ newFileLoc.append(state.substring(cp,
+ ncp = (state.indexOf("\"", ncp + 1) + 1)));
+ String oldfilenam = state.substring(ncp,
+ ecp = state.indexOf("\"", ncp));
+ // recover the new mapping data for this old filename
+ // have to normalize filename - since Jmol and jalview do
+ // filename
+ // translation differently.
+ Object[] filedat = oldFiles.get(new File(oldfilenam));
+ newFileLoc.append(Platform.escapeString((String) filedat[0]));
+ pdbfilenames.add((String) filedat[0]);
+ pdbids.add((String) filedat[1]);
+ seqmaps.add(((Vector<SequenceI>) filedat[2])
+ .toArray(new SequenceI[0]));
+ newFileLoc.append("\"");
+ cp = ecp + 1; // advance beyond last \" and set cursor so we can
+ // look for next file statement.
+ } while ((ncp = state.indexOf("/*file*/", cp)) > -1);
+ }
+ if (cp > 0)
+ {
+ // just append rest of state
+ newFileLoc.append(state.substring(cp));
+ }
+ else
+ {
+ System.err.print("Ignoring incomplete Jmol state for PDB ids: ");
+ newFileLoc = new StringBuilder(state);
+ newFileLoc.append("; load append ");
+ for (File id : oldFiles.keySet())
{
- String sviewid = entry.getKey();
- ViewerData svattrib = entry.getValue();
- String state = svattrib.stateData;
- Map<File, Object[]> oldFiles = svattrib.fileData;
- final boolean useinJmolsuperpos = svattrib.alignWithPanel;
- final boolean usetoColourbyseq = svattrib.colourWithAlignPanel;
- final boolean jmolColouring = svattrib.colourByViewer;
- int x = svattrib.x;
- int y = svattrib.y;
- int width = svattrib.width;
- int height = svattrib.height;
- // collate the pdbfile -> sequence mappings from this view
- Vector<String> pdbfilenames = new Vector<String>();
- Vector<SequenceI[]> seqmaps = new Vector<SequenceI[]>();
- Vector<String> pdbids = new Vector<String>();
+ // add this and any other pdb files that should be present in
+ // the viewer
+ Object[] filedat = oldFiles.get(id);
+ String nfilename;
+ newFileLoc.append(((String) filedat[0]));
+ pdbfilenames.add((String) filedat[0]);
+ pdbids.add((String) filedat[1]);
+ seqmaps.add(((Vector<SequenceI>) filedat[2])
+ .toArray(new SequenceI[0]));
+ newFileLoc.append(" \"");
+ newFileLoc.append((String) filedat[0]);
+ newFileLoc.append("\"");
- /*
- * Search for any Jmol windows already open from other alignment views
- * that exactly match the stored structure state
- */
- AppJmol comp = null;
- JInternalFrame[] frames = getAllFrames();
- for (JInternalFrame frame : frames)
- {
- if (frame instanceof AppJmol)
- {
- /*
- * Post jalview 2.4 schema includes structure view id
- */
- if (sviewid != null
- && ((StructureViewerBase) frame).getViewId().equals(
- sviewid))
- {
- comp = (AppJmol) frame;
- }
- /*
- * Otherwise test for matching position and size of viewer frame
- */
- else if (frame.getX() == x && frame.getY() == y
- && frame.getHeight() == height
- && frame.getWidth() == width)
- {
- comp = (AppJmol) frame;
- }
- }
- }
+ }
+ newFileLoc.append(";");
+ }
- if (comp == null)
+ if (newFileLoc.length() > 0)
+ {
+ int histbug = newFileLoc.indexOf("history = ");
+ histbug += 10;
+ int diff = histbug == -1 ? -1 : newFileLoc.indexOf(";", histbug);
+ String val = (diff == -1) ? null : newFileLoc
+ .substring(histbug, diff);
+ if (val != null && val.length() >= 4)
+ {
+ if (val.contains("e"))
{
- /*
- * Create a new Jmol window. First parse the Jmol state to translate
- * filenames loaded into the view, and record the order in which files
- * are shown in the Jmol view, so we can add the sequence mappings in
- * same order.
- */
- StringBuffer newFileLoc = null;
- int cp = 0, ncp, ecp;
- while ((ncp = state.indexOf("load ", cp)) > -1)
- {
- if (newFileLoc == null)
- {
- newFileLoc = new StringBuffer();
- }
- do
- {
- // look for next filename in load statement
- newFileLoc.append(state.substring(cp,
- ncp = (state.indexOf("\"", ncp + 1) + 1)));
- String oldfilenam = state.substring(ncp,
- ecp = state.indexOf("\"", ncp));
- // recover the new mapping data for this old filename
- // have to normalize filename - since Jmol and jalview do
- // filename
- // translation differently.
- Object[] filedat = oldFiles.get(new File(oldfilenam));
- newFileLoc.append(Platform
- .escapeString((String) filedat[0]));
- pdbfilenames.addElement((String) filedat[0]);
- pdbids.addElement((String) filedat[1]);
- seqmaps.addElement(((Vector<SequenceI>) filedat[2])
- .toArray(new SequenceI[0]));
- newFileLoc.append("\"");
- cp = ecp + 1; // advance beyond last \" and set cursor so we can
- // look for next file statement.
- } while ((ncp = state.indexOf("/*file*/", cp)) > -1);
- }
- if (cp > 0)
+ if (val.trim().equals("true"))
{
- // just append rest of state
- newFileLoc.append(state.substring(cp));
+ val = "1";
}
else
{
- System.err
- .print("Ignoring incomplete Jmol state for PDB ids: ");
- newFileLoc = new StringBuffer(state);
- newFileLoc.append("; load append ");
- for (File id : oldFiles.keySet())
- {
- // add this and any other pdb files that should be present in
- // the viewer
- Object[] filedat = oldFiles.get(id);
- String nfilename;
- newFileLoc.append(((String) filedat[0]));
- pdbfilenames.addElement((String) filedat[0]);
- pdbids.addElement((String) filedat[1]);
- seqmaps.addElement(((Vector<SequenceI>) filedat[2])
- .toArray(new SequenceI[0]));
- newFileLoc.append(" \"");
- newFileLoc.append((String) filedat[0]);
- newFileLoc.append("\"");
-
- }
- newFileLoc.append(";");
+ val = "0";
}
+ newFileLoc.replace(histbug, diff, val);
+ }
+ }
- if (newFileLoc != null)
+ final String[] pdbf = pdbfilenames.toArray(new String[pdbfilenames
+ .size()]);
+ final String[] id = pdbids.toArray(new String[pdbids.size()]);
+ final SequenceI[][] sq = seqmaps
+ .toArray(new SequenceI[seqmaps.size()][]);
+ final String fileloc = newFileLoc.toString();
+ final String sviewid = viewerData.getKey();
+ final AlignFrame alf = af;
+ final java.awt.Rectangle rect = new java.awt.Rectangle(svattrib.x,
+ svattrib.y, svattrib.width, svattrib.height);
+ try
+ {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable()
+ {
+ @Override
+ public void run()
{
- int histbug = newFileLoc.indexOf("history = ");
- histbug += 10;
- int diff = histbug == -1 ? -1 : newFileLoc.indexOf(";",
- histbug);
- String val = (diff == -1) ? null : newFileLoc.substring(
- histbug, diff);
- if (val != null && val.length() >= 4)
- {
- if (val.contains("e"))
- {
- if (val.trim().equals("true"))
- {
- val = "1";
- }
- else
- {
- val = "0";
- }
- newFileLoc.replace(histbug, diff, val);
- }
- }
- // TODO: assemble String[] { pdb files }, String[] { id for each
- // file }, orig_fileloc, SequenceI[][] {{ seqs_file 1 }, {
- // seqs_file 2}} from hash
- final String[] pdbf = pdbfilenames
- .toArray(new String[pdbfilenames.size()]), id = pdbids
- .toArray(new String[pdbids.size()]);
- final SequenceI[][] sq = seqmaps
- .toArray(new SequenceI[seqmaps.size()][]);
- final String fileloc = newFileLoc.toString(), vid = sviewid;
- final AlignFrame alf = af;
- final java.awt.Rectangle rect = new java.awt.Rectangle(x, y,
- width, height);
+ JalviewStructureDisplayI sview = null;
try
{
- javax.swing.SwingUtilities.invokeAndWait(new Runnable()
- {
- @Override
- public void run()
- {
- JalviewStructureDisplayI sview = null;
- try
- {
- // JAL-1333 note - we probably can't migrate Jmol views to UCSF Chimera!
- sview = new StructureViewer(alf.alignPanel
- .getStructureSelectionManager()).createView(
- StructureViewer.ViewerType.JMOL, pdbf, id, sq,
- alf.alignPanel,
- useinJmolsuperpos, usetoColourbyseq,
- jmolColouring, fileloc, rect, vid);
- addNewStructureViewer(sview);
- } catch (OutOfMemoryError ex)
- {
- new OOMWarning("restoring structure view for PDB id "
- + id, (OutOfMemoryError) ex.getCause());
- if (sview != null && sview.isVisible())
- {
- sview.closeViewer();
- sview.setVisible(false);
- sview.dispose();
- }
- }
- }
- });
- } catch (InvocationTargetException ex)
- {
- warn("Unexpected error when opening Jmol view.", ex);
-
- } catch (InterruptedException e)
+ // JAL-1333 note - we probably can't migrate Jmol views to UCSF
+ // Chimera!
+ sview = new StructureViewer(alf.alignPanel
+ .getStructureSelectionManager()).createView(
+ StructureViewer.ViewerType.JMOL, pdbf, id, sq,
+ alf.alignPanel, svattrib, fileloc, rect, sviewid);
+ addNewStructureViewer(sview);
+ } catch (OutOfMemoryError ex)
{
- // e.printStackTrace();
+ new OOMWarning("restoring structure view for PDB id " + id,
+ (OutOfMemoryError) ex.getCause());
+ if (sview != null && sview.isVisible())
+ {
+ sview.closeViewer();
+ sview.setVisible(false);
+ sview.dispose();
+ }
}
}
+ });
+ } catch (InvocationTargetException ex)
+ {
+ warn("Unexpected error when opening Jmol view.", ex);
+ } catch (InterruptedException e)
+ {
+ // e.printStackTrace();
+ }
+ }
+ }
+
+ /**
+ * Returns any open frame that matches given structure viewer data. The match
+ * is based on the unique viewId, or (for older project versions) the frame's
+ * geometry.
+ *
+ * @param viewerData
+ * @return
+ */
+ protected StructureViewerBase findMatchingViewer(
+ Entry<String, ViewerData> viewerData)
+ {
+ final String sviewid = viewerData.getKey();
+ final ViewerData svattrib = viewerData.getValue();
+ StructureViewerBase comp = null;
+ JInternalFrame[] frames = getAllFrames();
+ for (JInternalFrame frame : frames)
+ {
+ if (frame instanceof StructureViewerBase)
+ {
+ /*
+ * Post jalview 2.4 schema includes structure view id
+ */
+ if (sviewid != null
+ && ((StructureViewerBase) frame).getViewId().equals(
+ sviewid))
+ {
+ comp = (AppJmol) frame;
+ // todo: break?
}
- else
- // if (comp != null)
+ /*
+ * Otherwise test for matching position and size of viewer frame
+ */
+ else if (frame.getX() == svattrib.x && frame.getY() == svattrib.y
+ && frame.getHeight() == svattrib.height
+ && frame.getWidth() == svattrib.width)
{
- linkStructureViewer(ap, comp, oldFiles, useinJmolsuperpos,
- usetoColourbyseq, jmolColouring);
+ comp = (AppJmol) frame;
+ // todo: break?
}
}
}
+ return comp;
}
/**
- * Link an AlignmentPanel to an existing JMol viewer.
+ * Link an AlignmentPanel to an existing structure viewer.
*
* @param ap
* @param viewer
* @param oldFiles
- * @param useinJmolsuperpos
+ * @param useinViewerSuperpos
* @param usetoColourbyseq
- * @param jmolColouring
+ * @param viewerColouring
*/
- protected void linkStructureViewer(AlignmentPanel ap, AppJmol viewer,
- Map<File, Object[]> oldFiles,
- final boolean useinJmolsuperpos, final boolean usetoColourbyseq,
- final boolean jmolColouring)
+ protected void linkStructureViewer(AlignmentPanel ap,
+ StructureViewerBase viewer, ViewerData svattrib)
{
// NOTE: if the jalview project is part of a shared session then
// view synchronization should/could be done here.
- // add mapping for sequences in this view to an already open Jmol
- // instance
+ final boolean useinViewerSuperpos = svattrib.alignWithPanel;
+ final boolean usetoColourbyseq = svattrib.colourWithAlignPanel;
+ final boolean viewerColouring = svattrib.colourByViewer;
+ Map<File, Object[]> oldFiles = svattrib.fileData;
+
+ /*
+ * Add mapping for sequences in this view to an already open viewer
+ */
+ final AAStructureBindingModel binding = viewer.getBinding();
for (File id : oldFiles.keySet())
{
// add this and any other pdb files that should be present in the
String pdbFile = (String) filedat[0];
SequenceI[] seq = ((Vector<SequenceI>) filedat[2])
.toArray(new SequenceI[0]);
- viewer.jmb.getSsm().setMapping(seq, null, pdbFile,
+ binding
+ .getSsm()
+ .setMapping(seq, null, pdbFile,
jalview.io.AppletFormatAdapter.FILE);
- viewer.jmb.addSequenceForStructFile(pdbFile, seq);
+ binding.addSequenceForStructFile(pdbFile, seq);
}
- // and add the AlignmentPanel's reference to the Jmol view
+ // and add the AlignmentPanel's reference to the view panel
viewer.addAlignmentPanel(ap);
- if (useinJmolsuperpos)
+ if (useinViewerSuperpos)
{
viewer.useAlignmentPanelForSuperposition(ap);
}
}
if (usetoColourbyseq)
{
- viewer.useAlignmentPanelForColourbyseq(ap, !jmolColouring);
+ viewer.useAlignmentPanelForColourbyseq(ap, !viewerColouring);
}
else
{