From acb5aa4d23f04663b566940d67ae5bfeb549ba98 Mon Sep 17 00:00:00 2001 From: jprocter Date: Wed, 8 Sep 2010 14:14:39 +0000 Subject: [PATCH] JAL-634 --- src/jalview/gui/Jalview2XML.java | 517 ++++++++++++++++++++++++-------------- 1 file changed, 329 insertions(+), 188 deletions(-) diff --git a/src/jalview/gui/Jalview2XML.java b/src/jalview/gui/Jalview2XML.java index c9e8bdd..f0edf7a 100755 --- a/src/jalview/gui/Jalview2XML.java +++ b/src/jalview/gui/Jalview2XML.java @@ -22,6 +22,7 @@ import java.io.*; import java.lang.reflect.InvocationTargetException; import java.net.*; import java.util.*; +import java.util.Map.Entry; import java.util.jar.*; import javax.swing.*; @@ -413,7 +414,7 @@ public class Jalview2XML JarOutputStream jout) { initSeqRefs(); - + Vector jmolViewIds = new Vector(); // Vector userColours = new Vector(); AlignViewport av = ap.av; @@ -581,33 +582,58 @@ public class Jalview2XML { // TODO: revise schema to allow many:one PDB id binding to viewer jmol = (AppJmol) frames[f]; - if (!jmol.jmb.pdbentry[0].getId().equals(entry.getId()) - && !(entry.getId().length() > 4 && entry.getId() - .toLowerCase().startsWith( - jmol.jmb.pdbentry[0].getId().toLowerCase()))) - continue; - matchedFile = jmol.jmb.pdbentry[0].getFile(); // record the file so we - // can get at it if the ID - // match is ambiguous (e.g. - // 1QIP==1qipA) - StructureState state = new StructureState(); - state.setVisible(true); - state.setXpos(jmol.getX()); - state.setYpos(jmol.getY()); - state.setWidth(jmol.getWidth()); - state.setHeight(jmol.getHeight()); - state.setViewId(jmol.getViewId()); - String statestring = jmol.jmb.viewer.getStateInfo(); - if (state != null) - { - state.setContent(statestring.replaceAll("\n", "")); - } - for (int s = 0; s < jmol.jmb.sequence.length; s++) + for (int peid = 0; peid < jmol.jmb.pdbentry.length; peid++) { - for (int smap=0;smap -1) + if (!jmol.jmb.pdbentry[peid].getId().equals(entry.getId()) + && !(entry.getId().length() > 4 && entry + .getId() + .toLowerCase() + .startsWith( + jmol.jmb.pdbentry[peid].getId() + .toLowerCase()))) + continue; + if (matchedFile == null) + { + matchedFile = jmol.jmb.pdbentry[peid].getFile(); + } + else if (!matchedFile.equals(jmol.jmb.pdbentry[peid] + .getFile())) + { + Cache.log + .warn("Probably lost some PDB-Sequence mappings for this structure file (which apparently has same PDB Entry code): " + + jmol.jmb.pdbentry[peid].getFile()); + ; // record the + } + // file so we + // can get at it if the ID + // match is ambiguous (e.g. + // 1QIP==1qipA) + String statestring = jmol.jmb.viewer.getStateInfo(); + + for (int smap = 0; smap < jmol.jmb.sequence[peid].length; smap++) { - pdb.addStructureState(state); + if (jal.findIndex(jmol.jmb.sequence[peid][smap]) > -1) + { + StructureState state = new StructureState(); + state.setVisible(true); + state.setXpos(jmol.getX()); + state.setYpos(jmol.getY()); + state.setWidth(jmol.getWidth()); + state.setHeight(jmol.getHeight()); + state.setViewId(jmol.getViewId()); + if (!jmolViewIds.contains(state.getViewId())) + { + // Make sure we only store a Jmol state once in each XML + // document. + jmolViewIds.addElement(state.getViewId()); + state.setContent(statestring.replaceAll("\n", "")); + } + else + { + state.setContent("# duplicate state"); + } + pdb.addStructureState(state); + } } } } @@ -866,9 +892,8 @@ public class Jalview2XML ae.setPosition(a); if (aa[i].annotations[a].secondaryStructure != ' ' && aa[i].annotations[a].secondaryStructure != '\0') - ae - .setSecondaryStructure(aa[i].annotations[a].secondaryStructure - + ""); + ae.setSecondaryStructure(aa[i].annotations[a].secondaryStructure + + ""); if (aa[i].annotations[a].colour != null && aa[i].annotations[a].colour != java.awt.Color.black) @@ -967,8 +992,8 @@ public class Jalview2XML // /////////SAVE VIEWPORT Viewport view = new Viewport(); view.setTitle(ap.alignFrame.getTitle()); - view.setSequenceSetId(makeHashCode(av.getSequenceSetId(), av - .getSequenceSetId())); + view.setSequenceSetId(makeHashCode(av.getSequenceSetId(), + av.getSequenceSetId())); view.setId(av.getViewId()); view.setViewName(av.viewName); view.setGatheredViews(av.gatherViewsHere); @@ -1155,10 +1180,8 @@ public class Jalview2XML } Group g = new Group(); g.setName(grp); - g - .setDisplay(((Boolean) ap.seqPanel.seqCanvas - .getFeatureRenderer().featureGroups.get(grp)) - .booleanValue()); + g.setDisplay(((Boolean) ap.seqPanel.seqCanvas.getFeatureRenderer().featureGroups + .get(grp)).booleanValue()); fs.addGroup(g); groupsAdded.addElement(grp); } @@ -2090,10 +2113,11 @@ public class Jalview2XML anot[ae[aa].getPosition()] = new jalview.datamodel.Annotation( - ae[aa].getDisplayCharacter(), ae[aa].getDescription(), (ae[aa] - .getSecondaryStructure() == null || ae[aa] - .getSecondaryStructure().length() == 0) ? ' ' : ae[aa] - .getSecondaryStructure().charAt(0), ae[aa].getValue() + ae[aa].getDisplayCharacter(), ae[aa].getDescription(), + (ae[aa].getSecondaryStructure() == null || ae[aa] + .getSecondaryStructure().length() == 0) ? ' ' + : ae[aa].getSecondaryStructure().charAt(0), + ae[aa].getValue() ); // JBPNote: Consider verifying dataflow for IO of secondary @@ -2103,8 +2127,8 @@ public class Jalview2XML // { // anot[ae[aa].getPosition()].displayCharacter = ""; // } - anot[ae[aa].getPosition()].colour = new java.awt.Color(ae[aa] - .getColour()); + anot[ae[aa].getPosition()].colour = new java.awt.Color( + ae[aa].getColour()); } } jalview.datamodel.AlignmentAnnotation jaa = null; @@ -2230,9 +2254,7 @@ public class Jalview2XML groups[i].getDisplayText(), groups[i].getColourText(), groups[i].getStart(), groups[i].getEnd()); - sg - .setOutlineColour(new java.awt.Color(groups[i] - .getOutlineColour())); + sg.setOutlineColour(new java.awt.Color(groups[i].getOutlineColour())); sg.textColour = new java.awt.Color(groups[i].getTextCol1()); sg.textColour2 = new java.awt.Color(groups[i].getTextCol2()); @@ -2241,9 +2263,7 @@ public class Jalview2XML sg.thresholdTextColour = groups[i].getTextColThreshold(); if (groups[i].hasShowConsensusHistogram()) { - sg - .setShowConsensusHistogram(groups[i] - .isShowConsensusHistogram()); + sg.setShowConsensusHistogram(groups[i].isShowConsensusHistogram()); } ; if (groups[i].hasShowSequenceLogo()) @@ -2257,8 +2277,8 @@ public class Jalview2XML if (groups[i].getConsThreshold() != 0) { jalview.analysis.Conservation c = new jalview.analysis.Conservation( - "All", ResidueProperties.propHash, 3, sg - .getSequences(null), 0, sg.getWidth() - 1); + "All", ResidueProperties.propHash, 3, + sg.getSequences(null), 0, sg.getWidth() - 1); c.calculate(); c.verdict(false, 25); sg.cs.setConservation(c); @@ -2369,9 +2389,10 @@ public class Jalview2XML TreePanel tp = (TreePanel) retrieveExistingObj(tree.getId()); if (tp == null) { - tp = af.ShowNewickTree(new jalview.io.NewickFile(tree - .getNewick()), tree.getTitle(), tree.getWidth(), tree - .getHeight(), tree.getXpos(), tree.getYpos()); + tp = af.ShowNewickTree( + new jalview.io.NewickFile(tree.getNewick()), + tree.getTitle(), tree.getWidth(), tree.getHeight(), + tree.getXpos(), tree.getYpos()); if (tree.getId() != null) { // perhaps bind the tree id to something ? @@ -2434,6 +2455,10 @@ public class Jalview2XML // //LOAD STRUCTURES if (loadTreesAndStructures) { + // run through all PDB ids on the alignment, and collect mappings between + // jmol view ids and all sequences referring to it + Hashtable jmolViewIds = new Hashtable(); + for (int i = 0; i < JSEQ.length; i++) { if (JSEQ[i].getPdbidsCount() > 0) @@ -2458,145 +2483,261 @@ public class Jalview2XML int y = ids[p].getStructureState(s).getYpos(); int width = ids[p].getStructureState(s).getWidth(); int height = ids[p].getStructureState(s).getHeight(); - AppJmol comp = null; - JInternalFrame[] frames = null; - do + + // Probably don't need to do this anymore... + // Desktop.desktop.getComponentAt(x, y); + // TODO: NOW: check that this recovers the PDB file correctly. + String pdbFile = loadPDBFile(jprovider, ids[p].getId()); + jalview.datamodel.SequenceI seq = (jalview.datamodel.SequenceI) seqRefIds + .get(JSEQ[i].getId() + ""); + if (sviewid == null) { - try - { - frames = Desktop.desktop.getAllFrames(); - } catch (ArrayIndexOutOfBoundsException e) - { - // occasional No such child exceptions are thrown here... - frames = null; - try - { - Thread.sleep(10); - } catch (Exception f) - { - } - ; - } - } while (frames == null); - // search for any Jmol windows already open from other - // alignment views that exactly match the stored structure state - for (int f = 0; comp == null && f < frames.length; f++) + sviewid = "_jalview_pre2_4_" + x + "," + y + "," + width + + "," + height; + } + if (!jmolViewIds.containsKey(sviewid)) + { + jmolViewIds.put(sviewid, new Object[] + { new int[] + { x, y, width, height }, "", + new Hashtable() }); + } + // TODO: assemble String[] { pdb files }, String[] { id for each + // file }, orig_fileloc, SequenceI[][] {{ seqs_file 1 }, { + // seqs_file 2}} from hash + Object[] jmoldat = (Object[]) jmolViewIds.get(sviewid); + if (((String) jmoldat[1]).length() < ids[p] + .getStructureState(s).getContent().length()) { - if (frames[f] instanceof AppJmol) { - if (sviewid != null - && ((AppJmol) frames[f]).getViewId().equals( - sviewid)) - { - // post jalview 2.4 schema includes structure view id - comp = (AppJmol) frames[f]; - } - else if (frames[f].getX() == x && frames[f].getY() == y - && frames[f].getHeight() == height - && frames[f].getWidth() == width) - { - comp = (AppJmol) frames[f]; - } + jmoldat[1] = ids[p].getStructureState(s).getContent(); } } - // Probably don't need to do this anymore... - // Desktop.desktop.getComponentAt(x, y); - // TODO: NOW: check that this recovers the PDB file correctly. - String pdbFile = loadPDBFile(jprovider, ids[p].getId()); + Object[] seqstrmaps = (Object[]) ((Hashtable) jmoldat[2]) + .get(ids[p].getFile()); + if (seqstrmaps == null) + { + ((Hashtable) jmoldat[2]).put( + new File(ids[p].getFile()).toString(), + seqstrmaps = new Object[] + { pdbFile, ids[p].getId(), new Vector(), + new Vector() }); + } + if (!((Vector) seqstrmaps[2]).contains(seq)) + { + ((Vector) seqstrmaps[2]).addElement(seq); + // ((Vector)seqstrmaps[3]).addElement(n) : in principle, chains + // should be stored here : do we need to + // TODO: store and recover seq/pdb_id : chain mappings + } + } + } + } + } + { - jalview.datamodel.SequenceI[] seq = new jalview.datamodel.SequenceI[] - { (jalview.datamodel.SequenceI) seqRefIds.get(JSEQ[i].getId() - + "") }; + // Instantiate the associated Jmol views + for (Entry entry : jmolViewIds.entrySet()) + { + String sviewid = entry.getKey(); + Object[] svattrib = entry.getValue(); + int[] geom = (int[]) svattrib[0]; + String state = (String) svattrib[1]; + Hashtable oldFiles = (Hashtable) svattrib[2]; - if (comp == null) + int x = geom[0], y = geom[1], width = geom[2], height = geom[3]; + // collate the pdbfile -> sequence mappings from this view + Vector pdbfilenames = new Vector(); + Vector seqmaps = new Vector(); + Vector pdbids = new Vector(); + + // Search to see if we've already created this Jmol view + AppJmol comp = null; + JInternalFrame[] frames = null; + do + { + try + { + frames = Desktop.desktop.getAllFrames(); + } catch (ArrayIndexOutOfBoundsException e) + { + // occasional No such child exceptions are thrown here... + frames = null; + try { - // create a new Jmol window - String state = ids[p].getStructureState(s).getContent(); - StringBuffer newFileLoc = null; - int cp=0; - if ((cp=state.indexOf("load ")) > -1) - { - newFileLoc = new StringBuffer(state.substring(0, (cp=state - .indexOf("\"", cp+1)+1))); + Thread.sleep(10); + } catch (Exception f) + { + } + ; + } + } while (frames == null); + // search for any Jmol windows already open from other + // alignment views that exactly match the stored structure state + for (int f = 0; comp == null && f < frames.length; f++) + { + if (frames[f] instanceof AppJmol) + { + if (sviewid != null + && ((AppJmol) frames[f]).getViewId().equals(sviewid)) + { + // post jalview 2.4 schema includes structure view id + comp = (AppJmol) frames[f]; + } + else if (frames[f].getX() == x && frames[f].getY() == y + && frames[f].getHeight() == height + && frames[f].getWidth() == width) + { + comp = (AppJmol) frames[f]; + } + } + } - newFileLoc.append(jpdb.getFile()); - newFileLoc.append(state.substring(state.indexOf("\"", - cp+1))); - } - else - { - System.err - .println("Ignoring incomplete Jmol state for PDB " - + ids[p].getId()); + if (comp == null) + { + // 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(); + } + 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) + .toString()); + newFileLoc.append(((String) filedat[0])); + pdbfilenames.addElement((String) filedat[0]); + pdbids.addElement((String) filedat[1]); + seqmaps.addElement((SequenceI[]) ((Vector) 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. + } + 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 StringBuffer(state); + newFileLoc.append("; load append "); + for (String 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((SequenceI[]) ((Vector) filedat[2]) + .toArray(new SequenceI[0])); + newFileLoc.append(" \""); + newFileLoc.append((String) filedat[0]); + newFileLoc.append("\""); - newFileLoc = new StringBuffer(state); - newFileLoc.append("; load \""); - newFileLoc.append(jpdb.getFile()); - newFileLoc.append("\";"); - } + } + newFileLoc.append(";"); + } - if (newFileLoc != null) + if (newFileLoc != null) + { + 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")) { - 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.trim().equals("true")) { - if (val.contains("e")) { - if (val.trim().equals("true")) { - val = "1"; - } else { - val = "0"; - } - newFileLoc.replace(histbug, diff, val); - } - } - final String pdbf=pdbFile, id=ids[p].getId(), fileloc=newFileLoc.toString(),vid=sviewid; - final SequenceI[] sq=seq; - final AlignFrame alf = af; - final java.awt.Rectangle rect = new java.awt.Rectangle(x, - y, width, height); - try { - javax.swing.SwingUtilities.invokeAndWait(new Runnable() { - public void run() { - new AppJmol(pdbf, id, sq, alf.alignPanel, - fileloc, rect, vid); - } - }); + val = "1"; } - catch (InvocationTargetException ex) + else { - System.err.println("Unexpected error when opening Jmol view."); - ex.printStackTrace(); - } catch (InterruptedException e) - { - // e.printStackTrace(); + val = "0"; } + newFileLoc.replace(histbug, diff, val); } - } - else - // if (comp != null) + // TODO: assemble String[] { pdb files }, String[] { id for each + // file }, orig_fileloc, SequenceI[][] {{ seqs_file 1 }, { + // seqs_file 2}} from hash + final String[] pdbf = (String[]) pdbfilenames + .toArray(new String[pdbfilenames.size()]), id = (String[]) pdbids + .toArray(new String[pdbids.size()]); + final SequenceI[][] sq = (SequenceI[][]) 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); + try + { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() + { + public void run() + { + new AppJmol(pdbf, id, sq, alf.alignPanel, fileloc, + rect, vid); + } + }); + } catch (InvocationTargetException ex) + { + System.err + .println("Unexpected error when opening Jmol view."); + ex.printStackTrace(); + } catch (InterruptedException e) { - // NOTE: if the jalview project is part of a shared session then - // view synchronization should/could be done here. - - // add mapping for this sequence to the already open Jmol - // instance (if it doesn't already exist) - // These - StructureSelectionManager.getStructureSelectionManager() - .setMapping(seq, null, pdbFile, - jalview.io.AppletFormatAdapter.FILE); - - ((AppJmol) comp).jmb.addSequenceForStructFile(pdbFile, seq); + // e.printStackTrace(); } } + + } + else + // if (comp != null) + { + // 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 + for (String id : oldFiles.keySet()) + { + // add this and any other pdb files that should be present in the + // viewer + Object[] filedat = oldFiles.get(id); + String pdbFile = (String) filedat[0]; + SequenceI[] seq = (SequenceI[]) ((Vector) filedat[2]) + .toArray(new SequenceI[0]); + StructureSelectionManager.getStructureSelectionManager() + .setMapping(seq, null, pdbFile, + jalview.io.AppletFormatAdapter.FILE); + ((AppJmol) comp).jmb.addSequenceForStructFile(pdbFile, seq); + } } } } } - + // and finally return. return af; } @@ -2648,8 +2789,8 @@ public class Jalview2XML for (int r = 0; r < JSEQ[s].getHiddenSequencesCount(); r++) { - hidden.addSequence(al - .getSequenceAt(JSEQ[s].getHiddenSequences(r)), false); + hidden.addSequence( + al.getSequenceAt(JSEQ[s].getHiddenSequences(r)), false); } af.viewport.hideRepSequences(al.getSequenceAt(s), hidden); } @@ -2692,8 +2833,8 @@ public class Jalview2XML af.viewport.viewName = view.getViewName(); af.setInitialTabVisible(); } - af.setBounds(view.getXpos(), view.getYpos(), view.getWidth(), view - .getHeight()); + af.setBounds(view.getXpos(), view.getYpos(), view.getWidth(), + view.getHeight()); af.viewport.setShowAnnotation(view.getShowAnnotation()); af.viewport.setAbovePIDThreshold(view.getPidSelected()); @@ -2754,32 +2895,32 @@ public class Jalview2XML ); } - if (view.getAnnotationColours().getColourScheme().equals( - "None")) + if (view.getAnnotationColours().getColourScheme() + .equals("None")) { - cs = new AnnotationColourGradient(af.viewport.alignment - .getAlignmentAnnotation()[i], new java.awt.Color( - view.getAnnotationColours().getMinColour()), + cs = new AnnotationColourGradient( + af.viewport.alignment.getAlignmentAnnotation()[i], new java.awt.Color(view.getAnnotationColours() - .getMaxColour()), view - .getAnnotationColours().getAboveThreshold()); + .getMinColour()), new java.awt.Color(view + .getAnnotationColours().getMaxColour()), + view.getAnnotationColours().getAboveThreshold()); } else if (view.getAnnotationColours().getColourScheme() .startsWith("ucs")) { - cs = new AnnotationColourGradient(af.viewport.alignment - .getAlignmentAnnotation()[i], + cs = new AnnotationColourGradient( + af.viewport.alignment.getAlignmentAnnotation()[i], GetUserColourScheme(jms, view .getAnnotationColours().getColourScheme()), view.getAnnotationColours().getAboveThreshold()); } else { - cs = new AnnotationColourGradient(af.viewport.alignment - .getAlignmentAnnotation()[i], ColourSchemeProperty - .getColour(al, view.getAnnotationColours() - .getColourScheme()), view - .getAnnotationColours().getAboveThreshold()); + cs = new AnnotationColourGradient( + af.viewport.alignment.getAlignmentAnnotation()[i], + ColourSchemeProperty.getColour(al, view + .getAnnotationColours().getColourScheme()), + view.getAnnotationColours().getAboveThreshold()); } // Also use these settings for all the groups @@ -2986,8 +3127,8 @@ public class Jalview2XML af.setMenusFromViewport(af.viewport); // TODO: we don't need to do this if the viewport is aready visible. - Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(), view - .getHeight()); + Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(), + view.getHeight()); af.alignPanel.updateAnnotation(false); // recompute any autoannotation return af; } @@ -3321,8 +3462,8 @@ public class Jalview2XML /** * make a new dataset sequence and add it to refIds hash */ - djs = new jalview.datamodel.Sequence(ms.getName(), ms - .getSequence()); + djs = new jalview.datamodel.Sequence(ms.getName(), + ms.getSequence()); djs.setStart(jmap.getMap().getToLowest()); djs.setEnd(jmap.getMap().getToHighest()); djs.setVamsasId(uniqueSetSuffix + sqid); -- 1.7.10.2