2 * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.0b1)
3 * Copyright (C) 2014 The Jalview Authors
5 * This file is part of Jalview.
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 of the License, or (at your option) any later version.
11 * Jalview is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty
13 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 * PURPOSE. See the GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along with Jalview. If not, see <http://www.gnu.org/licenses/>.
17 * The Jalview Authors are detailed in the 'AUTHORS' file.
21 import java.awt.Rectangle;
23 import java.lang.reflect.InvocationTargetException;
26 import java.util.Map.Entry;
27 import java.util.jar.*;
31 import org.exolab.castor.xml.*;
33 import jalview.bin.Cache;
34 import jalview.datamodel.Alignment;
35 import jalview.datamodel.AlignmentAnnotation;
36 import jalview.datamodel.AlignmentI;
37 import jalview.datamodel.SequenceI;
38 import jalview.schemabinding.version2.*;
39 import jalview.schemes.*;
40 import jalview.util.Platform;
41 import jalview.util.jarInputStreamProvider;
42 import jalview.viewmodel.AlignmentViewport;
43 import jalview.ws.jws2.Jws2Discoverer;
44 import jalview.ws.jws2.dm.AAConSettings;
45 import jalview.ws.jws2.jabaws2.Jws2Instance;
46 import jalview.ws.params.ArgumentI;
47 import jalview.ws.params.AutoCalcSetting;
48 import jalview.ws.params.WsParamSetI;
51 * Write out the current jalview desktop state as a Jalview XML stream.
53 * Note: the vamsas objects referred to here are primitive versions of the
54 * VAMSAS project schema elements - they are not the same and most likely never
58 * @version $Revision: 1.134 $
60 public class Jalview2XML
63 * create/return unique hash string for sq
66 * @return new or existing unique string for sq
68 String seqHash(SequenceI sq)
70 if (seqsToIds == null)
74 if (seqsToIds.containsKey(sq))
76 return (String) seqsToIds.get(sq);
80 // create sequential key
81 String key = "sq" + (seqsToIds.size() + 1);
82 key = makeHashCode(sq, key); // check we don't have an external reference
84 seqsToIds.put(sq, key);
93 if (seqRefIds != null)
97 if (seqsToIds != null)
107 warn("clearSeqRefs called when _cleartables was not set. Doing nothing.");
108 // seqRefIds = new Hashtable();
109 // seqsToIds = new IdentityHashMap();
115 if (seqsToIds == null)
117 seqsToIds = new IdentityHashMap();
119 if (seqRefIds == null)
121 seqRefIds = new Hashtable();
126 * SequenceI reference -> XML ID string in jalview XML. Populated as XML reps
127 * of sequence objects are created.
129 java.util.IdentityHashMap seqsToIds = null;
132 * jalview XML Sequence ID to jalview sequence object reference (both dataset
133 * and alignment sequences. Populated as XML reps of sequence objects are
136 java.util.Hashtable seqRefIds = null; // key->SequenceI resolution
138 Vector frefedSequence = null;
140 boolean raiseGUI = true; // whether errors are raised in dialog boxes or not
146 public Jalview2XML(boolean raiseGUI)
148 this.raiseGUI = raiseGUI;
151 public void resolveFrefedSequences()
153 if (frefedSequence.size() > 0)
155 int r = 0, rSize = frefedSequence.size();
158 Object[] ref = (Object[]) frefedSequence.elementAt(r);
161 String sref = (String) ref[0];
162 if (seqRefIds.containsKey(sref))
164 if (ref[1] instanceof jalview.datamodel.Mapping)
166 SequenceI seq = (SequenceI) seqRefIds.get(sref);
167 while (seq.getDatasetSequence() != null)
169 seq = seq.getDatasetSequence();
171 ((jalview.datamodel.Mapping) ref[1]).setTo(seq);
175 if (ref[1] instanceof jalview.datamodel.AlignedCodonFrame)
177 SequenceI seq = (SequenceI) seqRefIds.get(sref);
178 while (seq.getDatasetSequence() != null)
180 seq = seq.getDatasetSequence();
183 && ref[2] instanceof jalview.datamodel.Mapping)
185 jalview.datamodel.Mapping mp = (jalview.datamodel.Mapping) ref[2];
186 ((jalview.datamodel.AlignedCodonFrame) ref[1]).addMap(
187 seq, mp.getTo(), mp.getMap());
192 .println("IMPLEMENTATION ERROR: Unimplemented forward sequence references for AlcodonFrames involving "
193 + ref[2].getClass() + " type objects.");
199 .println("IMPLEMENTATION ERROR: Unimplemented forward sequence references for "
200 + ref[1].getClass() + " type objects.");
203 frefedSequence.remove(r);
209 .println("IMPLEMENTATION WARNING: Unresolved forward reference for hash string "
211 + " with objecttype "
212 + ref[1].getClass());
219 frefedSequence.remove(r);
227 * This maintains a list of viewports, the key being the seqSetId. Important
228 * to set historyItem and redoList for multiple views
230 Hashtable viewportsAdded;
232 Hashtable annotationIds = new Hashtable();
234 String uniqueSetSuffix = "";
237 * List of pdbfiles added to Jar
239 Vector pdbfiles = null;
241 // SAVES SEVERAL ALIGNMENT WINDOWS TO SAME JARFILE
242 public void SaveState(File statefile)
246 FileOutputStream fos = new FileOutputStream(statefile);
247 JarOutputStream jout = new JarOutputStream(fos);
250 } catch (Exception e)
252 // TODO: inform user of the problem - they need to know if their data was
254 if (errorMessage == null)
256 errorMessage = "Couldn't write Jalview Archive to output file '"
257 + statefile + "' - See console error log for details";
261 errorMessage += "(output file was '" + statefile + "')";
269 * Writes a jalview project archive to the given Jar output stream.
273 public void SaveState(JarOutputStream jout)
275 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
282 Hashtable<String, AlignFrame> dsses = new Hashtable<String, AlignFrame>();
287 // NOTE UTF-8 MUST BE USED FOR WRITING UNICODE CHARS
288 // //////////////////////////////////////////////////
289 // NOTE ALSO new PrintWriter must be used for each new JarEntry
290 PrintWriter out = null;
292 Vector shortNames = new Vector();
295 for (int i = frames.length - 1; i > -1; i--)
297 if (frames[i] instanceof AlignFrame)
299 AlignFrame af = (AlignFrame) frames[i];
302 && skipList.containsKey(af.getViewport()
303 .getSequenceSetId()))
308 String shortName = af.getTitle();
310 if (shortName.indexOf(File.separatorChar) > -1)
312 shortName = shortName.substring(shortName
313 .lastIndexOf(File.separatorChar) + 1);
318 while (shortNames.contains(shortName))
320 if (shortName.endsWith("_" + (count - 1)))
322 shortName = shortName
323 .substring(0, shortName.lastIndexOf("_"));
326 shortName = shortName.concat("_" + count);
330 shortNames.addElement(shortName);
332 if (!shortName.endsWith(".xml"))
334 shortName = shortName + ".xml";
337 int ap, apSize = af.alignPanels.size();
339 for (ap = 0; ap < apSize; ap++)
341 AlignmentPanel apanel = (AlignmentPanel) af.alignPanels
343 String fileName = apSize == 1 ? shortName : ap + shortName;
344 if (!fileName.endsWith(".xml"))
346 fileName = fileName + ".xml";
349 SaveState(apanel, fileName, jout);
351 String dssid = getDatasetIdRef(af.getViewport().getAlignment()
353 if (!dsses.containsKey(dssid))
355 dsses.put(dssid, af);
362 writeDatasetFor(dsses, "" + jout.hashCode() + " " + uniqueSetSuffix,
368 } catch (Exception foo)
373 } catch (Exception ex)
375 // TODO: inform user of the problem - they need to know if their data was
377 if (errorMessage == null)
379 errorMessage = "Couldn't write Jalview Archive - see error output for details";
381 ex.printStackTrace();
385 // USE THIS METHOD TO SAVE A SINGLE ALIGNMENT WINDOW
386 public boolean SaveAlignment(AlignFrame af, String jarFile,
391 int ap, apSize = af.alignPanels.size();
392 FileOutputStream fos = new FileOutputStream(jarFile);
393 JarOutputStream jout = new JarOutputStream(fos);
394 Hashtable<String, AlignFrame> dsses = new Hashtable<String, AlignFrame>();
395 for (ap = 0; ap < apSize; ap++)
397 AlignmentPanel apanel = (AlignmentPanel) af.alignPanels
399 String jfileName = apSize == 1 ? fileName : fileName + ap;
400 if (!jfileName.endsWith(".xml"))
402 jfileName = jfileName + ".xml";
404 SaveState(apanel, jfileName, jout);
405 String dssid = getDatasetIdRef(af.getViewport().getAlignment()
407 if (!dsses.containsKey(dssid))
409 dsses.put(dssid, af);
412 writeDatasetFor(dsses, fileName, jout);
416 } catch (Exception foo)
422 } catch (Exception ex)
424 errorMessage = "Couldn't Write alignment view to Jalview Archive - see error output for details";
425 ex.printStackTrace();
430 private void writeDatasetFor(Hashtable<String, AlignFrame> dsses,
431 String fileName, JarOutputStream jout)
434 for (String dssids : dsses.keySet())
436 AlignFrame _af = dsses.get(dssids);
437 String jfileName = fileName + " Dataset for " + _af.getTitle();
438 if (!jfileName.endsWith(".xml"))
440 jfileName = jfileName + ".xml";
442 SaveState(_af.alignPanel, jfileName, true, jout);
447 * create a JalviewModel from an algnment view and marshall it to a
451 * panel to create jalview model for
453 * name of alignment panel written to output stream
459 public JalviewModel SaveState(AlignmentPanel ap, String fileName,
460 JarOutputStream jout)
462 return SaveState(ap, fileName, false, jout);
466 * create a JalviewModel from an algnment view and marshall it to a
470 * panel to create jalview model for
472 * name of alignment panel written to output stream
474 * when true, only write the dataset for the alignment, not the data
475 * associated with the view.
481 public JalviewModel SaveState(AlignmentPanel ap, String fileName,
482 boolean storeDS, JarOutputStream jout)
485 Vector jmolViewIds = new Vector(); //
486 Vector userColours = new Vector();
488 AlignViewport av = ap.av;
490 JalviewModel object = new JalviewModel();
491 object.setVamsasModel(new jalview.schemabinding.version2.VamsasModel());
493 object.setCreationDate(new java.util.Date(System.currentTimeMillis()));
494 object.setVersion(jalview.bin.Cache.getDefault("VERSION",
495 "Development Build"));
497 jalview.datamodel.AlignmentI jal = av.getAlignment();
499 if (av.hasHiddenRows())
501 jal = jal.getHiddenSequences().getFullAlignment();
504 SequenceSet vamsasSet = new SequenceSet();
506 JalviewModelSequence jms = new JalviewModelSequence();
508 vamsasSet.setGapChar(jal.getGapCharacter() + "");
510 if (jal.getDataset() != null)
512 // dataset id is the dataset's hashcode
513 vamsasSet.setDatasetId(getDatasetIdRef(jal.getDataset()));
516 // switch jal and the dataset
517 jal = jal.getDataset();
520 if (jal.getProperties() != null)
522 Enumeration en = jal.getProperties().keys();
523 while (en.hasMoreElements())
525 String key = en.nextElement().toString();
526 SequenceSetProperties ssp = new SequenceSetProperties();
528 ssp.setValue(jal.getProperties().get(key).toString());
529 vamsasSet.addSequenceSetProperties(ssp);
534 Set<String> calcIdSet = new HashSet<String>();
538 jalview.datamodel.SequenceI jds, jdatasq;
539 for (int i = 0; i < jal.getHeight(); i++)
541 jds = jal.getSequenceAt(i);
542 jdatasq = jds.getDatasetSequence() == null ? jds : jds
543 .getDatasetSequence();
546 if (seqRefIds.get(id) != null)
548 // This happens for two reasons: 1. multiple views are being serialised.
549 // 2. the hashCode has collided with another sequence's code. This DOES
550 // HAPPEN! (PF00072.15.stk does this)
551 // JBPNote: Uncomment to debug writing out of files that do not read
552 // back in due to ArrayOutOfBoundExceptions.
553 // System.err.println("vamsasSeq backref: "+id+"");
554 // System.err.println(jds.getName()+"
555 // "+jds.getStart()+"-"+jds.getEnd()+" "+jds.getSequenceAsString());
556 // System.err.println("Hashcode: "+seqHash(jds));
557 // SequenceI rsq = (SequenceI) seqRefIds.get(id + "");
558 // System.err.println(rsq.getName()+"
559 // "+rsq.getStart()+"-"+rsq.getEnd()+" "+rsq.getSequenceAsString());
560 // System.err.println("Hashcode: "+seqHash(rsq));
564 vamsasSeq = createVamsasSequence(id, jds);
565 vamsasSet.addSequence(vamsasSeq);
566 seqRefIds.put(id, jds);
570 jseq.setStart(jds.getStart());
571 jseq.setEnd(jds.getEnd());
572 jseq.setColour(av.getSequenceColour(jds).getRGB());
574 jseq.setId(id); // jseq id should be a string not a number
577 // Store any sequences this sequence represents
578 if (av.hasHiddenRows())
580 jseq.setHidden(av.getAlignment().getHiddenSequences()
583 if (av.isHiddenRepSequence(jal.getSequenceAt(i)))
585 jalview.datamodel.SequenceI[] reps = av
586 .getRepresentedSequences(jal.getSequenceAt(i))
587 .getSequencesInOrder(jal);
589 for (int h = 0; h < reps.length; h++)
591 if (reps[h] != jal.getSequenceAt(i))
593 jseq.addHiddenSequences(jal.findIndex(reps[h]));
600 if (jdatasq.getSequenceFeatures() != null)
602 jalview.datamodel.SequenceFeature[] sf = jdatasq
603 .getSequenceFeatures();
605 while (index < sf.length)
607 Features features = new Features();
609 features.setBegin(sf[index].getBegin());
610 features.setEnd(sf[index].getEnd());
611 features.setDescription(sf[index].getDescription());
612 features.setType(sf[index].getType());
613 features.setFeatureGroup(sf[index].getFeatureGroup());
614 features.setScore(sf[index].getScore());
615 if (sf[index].links != null)
617 for (int l = 0; l < sf[index].links.size(); l++)
619 OtherData keyValue = new OtherData();
620 keyValue.setKey("LINK_" + l);
621 keyValue.setValue(sf[index].links.elementAt(l).toString());
622 features.addOtherData(keyValue);
625 if (sf[index].otherDetails != null)
628 Enumeration keys = sf[index].otherDetails.keys();
629 while (keys.hasMoreElements())
631 key = keys.nextElement().toString();
632 OtherData keyValue = new OtherData();
633 keyValue.setKey(key);
634 keyValue.setValue(sf[index].otherDetails.get(key).toString());
635 features.addOtherData(keyValue);
639 jseq.addFeatures(features);
644 if (jdatasq.getPDBId() != null)
646 Enumeration en = jdatasq.getPDBId().elements();
647 while (en.hasMoreElements())
649 Pdbids pdb = new Pdbids();
650 jalview.datamodel.PDBEntry entry = (jalview.datamodel.PDBEntry) en
653 pdb.setId(entry.getId());
654 pdb.setType(entry.getType());
656 // store any JMol views associated with this seqeunce
657 // this section copes with duplicate entries in the project, so a
658 // dataset only view *should* be coped with sensibly
660 // This must have been loaded, is it still visible?
661 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
662 String matchedFile = null;
663 for (int f = frames.length - 1; f > -1; f--)
665 if (frames[f] instanceof AppJmol)
667 jmol = (AppJmol) frames[f];
668 for (int peid = 0; peid < jmol.jmb.pdbentry.length; peid++)
670 if (!jmol.jmb.pdbentry[peid].getId().equals(entry.getId())
671 && !(entry.getId().length() > 4 && entry
675 jmol.jmb.pdbentry[peid].getId()
678 if (matchedFile == null)
680 matchedFile = jmol.jmb.pdbentry[peid].getFile();
682 else if (!matchedFile.equals(jmol.jmb.pdbentry[peid]
686 .warn("Probably lost some PDB-Sequence mappings for this structure file (which apparently has same PDB Entry code): "
687 + jmol.jmb.pdbentry[peid].getFile());
691 // can get at it if the ID
692 // match is ambiguous (e.g.
694 String statestring = jmol.jmb.viewer.getStateInfo();
696 for (int smap = 0; smap < jmol.jmb.sequence[peid].length; smap++)
698 // if (jal.findIndex(jmol.jmb.sequence[peid][smap]) > -1)
699 if (jds == jmol.jmb.sequence[peid][smap])
701 StructureState state = new StructureState();
702 state.setVisible(true);
703 state.setXpos(jmol.getX());
704 state.setYpos(jmol.getY());
705 state.setWidth(jmol.getWidth());
706 state.setHeight(jmol.getHeight());
707 state.setViewId(jmol.getViewId());
708 state.setAlignwithAlignPanel(jmol.isUsedforaligment(ap));
709 state.setColourwithAlignPanel(jmol
710 .isUsedforcolourby(ap));
711 state.setColourByJmol(jmol.isColouredByJmol());
712 if (!jmolViewIds.contains(state.getViewId()))
714 // Make sure we only store a Jmol state once in each XML
716 jmolViewIds.addElement(state.getViewId());
717 state.setContent(statestring.replaceAll("\n", ""));
721 state.setContent("# duplicate state");
723 pdb.addStructureState(state);
731 if (matchedFile != null || entry.getFile() != null)
733 if (entry.getFile() != null)
736 matchedFile = entry.getFile();
738 pdb.setFile(matchedFile); // entry.getFile());
739 if (pdbfiles == null)
741 pdbfiles = new Vector();
744 if (!pdbfiles.contains(entry.getId()))
746 pdbfiles.addElement(entry.getId());
749 File file = new File(matchedFile);
750 if (file.exists() && jout != null)
752 byte[] data = new byte[(int) file.length()];
753 jout.putNextEntry(new JarEntry(entry.getId()));
754 DataInputStream dis = new DataInputStream(
755 new FileInputStream(file));
758 DataOutputStream dout = new DataOutputStream(jout);
759 dout.write(data, 0, data.length);
763 } catch (Exception ex)
765 ex.printStackTrace();
771 if (entry.getProperty() != null)
773 PdbentryItem item = new PdbentryItem();
774 Hashtable properties = entry.getProperty();
775 Enumeration en2 = properties.keys();
776 while (en2.hasMoreElements())
778 Property prop = new Property();
779 String key = en2.nextElement().toString();
781 prop.setValue(properties.get(key).toString());
782 item.addProperty(prop);
784 pdb.addPdbentryItem(item);
794 if (!storeDS && av.hasHiddenRows())
796 jal = av.getAlignment();
799 if (jal.getCodonFrames() != null && jal.getCodonFrames().length > 0)
801 jalview.datamodel.AlignedCodonFrame[] jac = jal.getCodonFrames();
802 for (int i = 0; i < jac.length; i++)
804 AlcodonFrame alc = new AlcodonFrame();
805 vamsasSet.addAlcodonFrame(alc);
806 for (int p = 0; p < jac[i].aaWidth; p++)
808 Alcodon cmap = new Alcodon();
809 if (jac[i].codons[p] != null)
811 // Null codons indicate a gapped column in the translated peptide
813 cmap.setPos1(jac[i].codons[p][0]);
814 cmap.setPos2(jac[i].codons[p][1]);
815 cmap.setPos3(jac[i].codons[p][2]);
817 alc.addAlcodon(cmap);
819 if (jac[i].getProtMappings() != null
820 && jac[i].getProtMappings().length > 0)
822 SequenceI[] dnas = jac[i].getdnaSeqs();
823 jalview.datamodel.Mapping[] pmaps = jac[i].getProtMappings();
824 for (int m = 0; m < pmaps.length; m++)
826 AlcodMap alcmap = new AlcodMap();
827 alcmap.setDnasq(seqHash(dnas[m]));
828 alcmap.setMapping(createVamsasMapping(pmaps[m], dnas[m], null,
830 alc.addAlcodMap(alcmap);
837 // /////////////////////////////////
838 if (!storeDS && av.currentTree != null)
840 // FIND ANY ASSOCIATED TREES
841 // NOT IMPLEMENTED FOR HEADLESS STATE AT PRESENT
842 if (Desktop.desktop != null)
844 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
846 for (int t = 0; t < frames.length; t++)
848 if (frames[t] instanceof TreePanel)
850 TreePanel tp = (TreePanel) frames[t];
852 if (tp.treeCanvas.av.getAlignment() == jal)
854 Tree tree = new Tree();
855 tree.setTitle(tp.getTitle());
856 tree.setCurrentTree((av.currentTree == tp.getTree()));
857 tree.setNewick(tp.getTree().toString());
858 tree.setThreshold(tp.treeCanvas.threshold);
860 tree.setFitToWindow(tp.fitToWindow.getState());
861 tree.setFontName(tp.getTreeFont().getName());
862 tree.setFontSize(tp.getTreeFont().getSize());
863 tree.setFontStyle(tp.getTreeFont().getStyle());
864 tree.setMarkUnlinked(tp.placeholdersMenu.getState());
866 tree.setShowBootstrap(tp.bootstrapMenu.getState());
867 tree.setShowDistances(tp.distanceMenu.getState());
869 tree.setHeight(tp.getHeight());
870 tree.setWidth(tp.getWidth());
871 tree.setXpos(tp.getX());
872 tree.setYpos(tp.getY());
873 tree.setId(makeHashCode(tp, null));
882 * store forward refs from an annotationRow to any groups
884 IdentityHashMap groupRefs = new IdentityHashMap();
887 for (SequenceI sq : jal.getSequences())
889 // Store annotation on dataset sequences only
890 jalview.datamodel.AlignmentAnnotation[] aa = sq.getAnnotation();
891 if (aa != null && aa.length > 0)
893 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
900 if (jal.getAlignmentAnnotation() != null)
902 // Store the annotation shown on the alignment.
903 jalview.datamodel.AlignmentAnnotation[] aa = jal
904 .getAlignmentAnnotation();
905 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
910 if (jal.getGroups() != null)
912 JGroup[] groups = new JGroup[jal.getGroups().size()];
914 for (jalview.datamodel.SequenceGroup sg : jal.getGroups())
916 groups[++i] = new JGroup();
918 groups[i].setStart(sg.getStartRes());
919 groups[i].setEnd(sg.getEndRes());
920 groups[i].setName(sg.getName());
921 if (groupRefs.containsKey(sg))
923 // group has references so set it's ID field
924 groups[i].setId(groupRefs.get(sg).toString());
928 if (sg.cs.conservationApplied())
930 groups[i].setConsThreshold(sg.cs.getConservationInc());
932 if (sg.cs instanceof jalview.schemes.UserColourScheme)
934 groups[i].setColour(SetUserColourScheme(sg.cs, userColours,
940 .setColour(ColourSchemeProperty.getColourName(sg.cs));
943 else if (sg.cs instanceof jalview.schemes.AnnotationColourGradient)
946 .setColour(ColourSchemeProperty
947 .getColourName(((jalview.schemes.AnnotationColourGradient) sg.cs)
950 else if (sg.cs instanceof jalview.schemes.UserColourScheme)
953 .setColour(SetUserColourScheme(sg.cs, userColours, jms));
957 groups[i].setColour(ColourSchemeProperty.getColourName(sg.cs));
960 groups[i].setPidThreshold(sg.cs.getThreshold());
963 groups[i].setOutlineColour(sg.getOutlineColour().getRGB());
964 groups[i].setDisplayBoxes(sg.getDisplayBoxes());
965 groups[i].setDisplayText(sg.getDisplayText());
966 groups[i].setColourText(sg.getColourText());
967 groups[i].setTextCol1(sg.textColour.getRGB());
968 groups[i].setTextCol2(sg.textColour2.getRGB());
969 groups[i].setTextColThreshold(sg.thresholdTextColour);
970 groups[i].setShowUnconserved(sg.getShowNonconserved());
971 groups[i].setIgnoreGapsinConsensus(sg.getIgnoreGapsConsensus());
972 groups[i].setShowConsensusHistogram(sg.isShowConsensusHistogram());
973 groups[i].setShowSequenceLogo(sg.isShowSequenceLogo());
974 groups[i].setNormaliseSequenceLogo(sg.isNormaliseSequenceLogo());
975 for (int s = 0; s < sg.getSize(); s++)
977 jalview.datamodel.Sequence seq = (jalview.datamodel.Sequence) sg
979 groups[i].addSeq(seqHash(seq));
983 jms.setJGroup(groups);
987 // /////////SAVE VIEWPORT
988 Viewport view = new Viewport();
989 view.setTitle(ap.alignFrame.getTitle());
990 view.setSequenceSetId(makeHashCode(av.getSequenceSetId(),
991 av.getSequenceSetId()));
992 view.setId(av.getViewId());
993 view.setViewName(av.viewName);
994 view.setGatheredViews(av.gatherViewsHere);
996 if (ap.av.explodedPosition != null)
998 view.setXpos(av.explodedPosition.x);
999 view.setYpos(av.explodedPosition.y);
1000 view.setWidth(av.explodedPosition.width);
1001 view.setHeight(av.explodedPosition.height);
1005 view.setXpos(ap.alignFrame.getBounds().x);
1006 view.setYpos(ap.alignFrame.getBounds().y);
1007 view.setWidth(ap.alignFrame.getBounds().width);
1008 view.setHeight(ap.alignFrame.getBounds().height);
1011 view.setStartRes(av.startRes);
1012 view.setStartSeq(av.startSeq);
1014 if (av.getGlobalColourScheme() instanceof jalview.schemes.UserColourScheme)
1016 view.setBgColour(SetUserColourScheme(av.getGlobalColourScheme(),
1019 else if (av.getGlobalColourScheme() instanceof jalview.schemes.AnnotationColourGradient)
1021 jalview.schemes.AnnotationColourGradient acg = (jalview.schemes.AnnotationColourGradient) av
1022 .getGlobalColourScheme();
1024 AnnotationColours ac = new AnnotationColours();
1025 ac.setAboveThreshold(acg.getAboveThreshold());
1026 ac.setThreshold(acg.getAnnotationThreshold());
1027 ac.setAnnotation(acg.getAnnotation());
1028 if (acg.getBaseColour() instanceof jalview.schemes.UserColourScheme)
1030 ac.setColourScheme(SetUserColourScheme(acg.getBaseColour(),
1035 ac.setColourScheme(ColourSchemeProperty.getColourName(acg
1039 ac.setMaxColour(acg.getMaxColour().getRGB());
1040 ac.setMinColour(acg.getMinColour().getRGB());
1041 ac.setPerSequence(acg.isSeqAssociated());
1042 ac.setPredefinedColours(acg.isPredefinedColours());
1043 view.setAnnotationColours(ac);
1044 view.setBgColour("AnnotationColourGradient");
1048 view.setBgColour(ColourSchemeProperty.getColourName(av
1049 .getGlobalColourScheme()));
1052 ColourSchemeI cs = av.getGlobalColourScheme();
1056 if (cs.conservationApplied())
1058 view.setConsThreshold(cs.getConservationInc());
1059 if (cs instanceof jalview.schemes.UserColourScheme)
1061 view.setBgColour(SetUserColourScheme(cs, userColours, jms));
1065 if (cs instanceof ResidueColourScheme)
1067 view.setPidThreshold(cs.getThreshold());
1071 view.setConservationSelected(av.getConservationSelected());
1072 view.setPidSelected(av.getAbovePIDThreshold());
1073 view.setFontName(av.font.getName());
1074 view.setFontSize(av.font.getSize());
1075 view.setFontStyle(av.font.getStyle());
1076 view.setRenderGaps(av.renderGaps);
1077 view.setShowAnnotation(av.getShowAnnotation());
1078 view.setShowBoxes(av.getShowBoxes());
1079 view.setShowColourText(av.getColourText());
1080 view.setShowFullId(av.getShowJVSuffix());
1081 view.setRightAlignIds(av.rightAlignIds);
1082 view.setShowSequenceFeatures(av.showSequenceFeatures);
1083 view.setShowText(av.getShowText());
1084 view.setShowUnconserved(av.getShowUnconserved());
1085 view.setWrapAlignment(av.getWrapAlignment());
1086 view.setTextCol1(av.textColour.getRGB());
1087 view.setTextCol2(av.textColour2.getRGB());
1088 view.setTextColThreshold(av.thresholdTextColour);
1089 view.setShowConsensusHistogram(av.isShowConsensusHistogram());
1090 view.setShowSequenceLogo(av.isShowSequenceLogo());
1091 view.setNormaliseSequenceLogo(av.isNormaliseSequenceLogo());
1092 view.setShowGroupConsensus(av.isShowGroupConsensus());
1093 view.setShowGroupConservation(av.isShowGroupConservation());
1094 view.setShowNPfeatureTooltip(av.isShowNpFeats());
1095 view.setShowDbRefTooltip(av.isShowDbRefs());
1096 view.setFollowHighlight(av.followHighlight);
1097 view.setFollowSelection(av.followSelection);
1098 view.setIgnoreGapsinConsensus(av.getIgnoreGapsConsensus());
1099 if (av.featuresDisplayed != null)
1101 jalview.schemabinding.version2.FeatureSettings fs = new jalview.schemabinding.version2.FeatureSettings();
1103 String[] renderOrder = ap.seqPanel.seqCanvas.getFeatureRenderer().renderOrder;
1105 Vector settingsAdded = new Vector();
1106 Object gstyle = null;
1107 GraduatedColor gcol = null;
1108 if (renderOrder != null)
1110 for (int ro = 0; ro < renderOrder.length; ro++)
1112 gstyle = ap.seqPanel.seqCanvas.getFeatureRenderer()
1113 .getFeatureStyle(renderOrder[ro]);
1114 Setting setting = new Setting();
1115 setting.setType(renderOrder[ro]);
1116 if (gstyle instanceof GraduatedColor)
1118 gcol = (GraduatedColor) gstyle;
1119 setting.setColour(gcol.getMaxColor().getRGB());
1120 setting.setMincolour(gcol.getMinColor().getRGB());
1121 setting.setMin(gcol.getMin());
1122 setting.setMax(gcol.getMax());
1123 setting.setColourByLabel(gcol.isColourByLabel());
1124 setting.setAutoScale(gcol.isAutoScale());
1125 setting.setThreshold(gcol.getThresh());
1126 setting.setThreshstate(gcol.getThreshType());
1130 setting.setColour(ap.seqPanel.seqCanvas.getFeatureRenderer()
1131 .getColour(renderOrder[ro]).getRGB());
1134 setting.setDisplay(av.featuresDisplayed
1135 .containsKey(renderOrder[ro]));
1136 float rorder = ap.seqPanel.seqCanvas.getFeatureRenderer()
1137 .getOrder(renderOrder[ro]);
1140 setting.setOrder(rorder);
1142 fs.addSetting(setting);
1143 settingsAdded.addElement(renderOrder[ro]);
1147 // Make sure we save none displayed feature settings
1148 Iterator en = ap.seqPanel.seqCanvas.getFeatureRenderer().featureColours
1149 .keySet().iterator();
1150 while (en.hasNext())
1152 String key = en.next().toString();
1153 if (settingsAdded.contains(key))
1158 Setting setting = new Setting();
1159 setting.setType(key);
1160 setting.setColour(ap.seqPanel.seqCanvas.getFeatureRenderer()
1161 .getColour(key).getRGB());
1163 setting.setDisplay(false);
1164 float rorder = ap.seqPanel.seqCanvas.getFeatureRenderer()
1168 setting.setOrder(rorder);
1170 fs.addSetting(setting);
1171 settingsAdded.addElement(key);
1173 en = ap.seqPanel.seqCanvas.getFeatureRenderer().featureGroups
1174 .keySet().iterator();
1175 Vector groupsAdded = new Vector();
1176 while (en.hasNext())
1178 String grp = en.next().toString();
1179 if (groupsAdded.contains(grp))
1183 Group g = new Group();
1185 g.setDisplay(((Boolean) ap.seqPanel.seqCanvas
1186 .getFeatureRenderer().featureGroups.get(grp))
1189 groupsAdded.addElement(grp);
1191 jms.setFeatureSettings(fs);
1195 if (av.hasHiddenColumns())
1197 if (av.getColumnSelection() == null
1198 || av.getColumnSelection().getHiddenColumns() == null)
1200 warn("REPORT BUG: avoided null columnselection bug (DMAM reported). Please contact Jim about this.");
1204 for (int c = 0; c < av.getColumnSelection().getHiddenColumns()
1207 int[] region = (int[]) av.getColumnSelection()
1208 .getHiddenColumns().elementAt(c);
1209 HiddenColumns hc = new HiddenColumns();
1210 hc.setStart(region[0]);
1211 hc.setEnd(region[1]);
1212 view.addHiddenColumns(hc);
1216 if (calcIdSet.size() > 0)
1218 for (String calcId : calcIdSet)
1220 if (calcId.trim().length() > 0)
1222 CalcIdParam cidp = createCalcIdParam(calcId, av);
1223 // Some calcIds have no parameters.
1226 view.addCalcIdParam(cidp);
1232 jms.addViewport(view);
1234 object.setJalviewModelSequence(jms);
1235 object.getVamsasModel().addSequenceSet(vamsasSet);
1237 if (jout != null && fileName != null)
1239 // We may not want to write the object to disk,
1240 // eg we can copy the alignViewport to a new view object
1241 // using save and then load
1244 JarEntry entry = new JarEntry(fileName);
1245 jout.putNextEntry(entry);
1246 PrintWriter pout = new PrintWriter(new OutputStreamWriter(jout,
1248 org.exolab.castor.xml.Marshaller marshaller = new org.exolab.castor.xml.Marshaller(
1250 marshaller.marshal(object);
1253 } catch (Exception ex)
1255 // TODO: raise error in GUI if marshalling failed.
1256 ex.printStackTrace();
1262 private void storeAlignmentAnnotation(AlignmentAnnotation[] aa, IdentityHashMap groupRefs, AlignmentViewport av, Set<String> calcIdSet, boolean storeDS, SequenceSet vamsasSet)
1265 for (int i = 0; i < aa.length; i++)
1267 Annotation an = new Annotation();
1269 if (aa[i].annotationId != null)
1271 annotationIds.put(aa[i].annotationId, aa[i]);
1274 an.setId(aa[i].annotationId);
1276 an.setVisible(aa[i].visible);
1278 an.setDescription(aa[i].description);
1280 if (aa[i].sequenceRef != null)
1282 // TODO later annotation sequenceRef should be the XML ID of the
1283 // sequence rather than its display name
1284 an.setSequenceRef(aa[i].sequenceRef.getName());
1286 if (aa[i].groupRef != null)
1288 Object groupIdr = groupRefs.get(aa[i].groupRef);
1289 if (groupIdr == null)
1291 // make a locally unique String
1292 groupRefs.put(aa[i].groupRef,
1293 groupIdr = ("" + System.currentTimeMillis()
1294 + aa[i].groupRef.getName() + groupRefs.size()));
1296 an.setGroupRef(groupIdr.toString());
1299 // store all visualization attributes for annotation
1300 an.setGraphHeight(aa[i].graphHeight);
1301 an.setCentreColLabels(aa[i].centreColLabels);
1302 an.setScaleColLabels(aa[i].scaleColLabel);
1303 an.setShowAllColLabels(aa[i].showAllColLabels);
1304 an.setBelowAlignment(aa[i].belowAlignment);
1306 if (aa[i].graph > 0)
1309 an.setGraphType(aa[i].graph);
1310 an.setGraphGroup(aa[i].graphGroup);
1311 if (aa[i].getThreshold() != null)
1313 ThresholdLine line = new ThresholdLine();
1314 line.setLabel(aa[i].getThreshold().label);
1315 line.setValue(aa[i].getThreshold().value);
1316 line.setColour(aa[i].getThreshold().colour.getRGB());
1317 an.setThresholdLine(line);
1325 an.setLabel(aa[i].label);
1327 if (aa[i] == av.getAlignmentQualityAnnot()
1328 || aa[i] == av.getAlignmentConservationAnnotation()
1329 || aa[i] == av.getAlignmentConsensusAnnotation()
1330 || aa[i].autoCalculated)
1332 // new way of indicating autocalculated annotation -
1333 an.setAutoCalculated(aa[i].autoCalculated);
1335 if (aa[i].hasScore())
1337 an.setScore(aa[i].getScore());
1340 if (aa[i].getCalcId() != null)
1342 calcIdSet.add(aa[i].getCalcId());
1343 an.setCalcId(aa[i].getCalcId());
1346 AnnotationElement ae;
1347 if (aa[i].annotations != null)
1349 an.setScoreOnly(false);
1350 for (int a = 0; a < aa[i].annotations.length; a++)
1352 if ((aa[i] == null) || (aa[i].annotations[a] == null))
1357 ae = new AnnotationElement();
1358 if (aa[i].annotations[a].description != null)
1359 ae.setDescription(aa[i].annotations[a].description);
1360 if (aa[i].annotations[a].displayCharacter != null)
1361 ae.setDisplayCharacter(aa[i].annotations[a].displayCharacter);
1363 if (!Float.isNaN(aa[i].annotations[a].value))
1364 ae.setValue(aa[i].annotations[a].value);
1367 if (aa[i].annotations[a].secondaryStructure != ' '
1368 && aa[i].annotations[a].secondaryStructure != '\0')
1369 ae.setSecondaryStructure(aa[i].annotations[a].secondaryStructure
1372 if (aa[i].annotations[a].colour != null
1373 && aa[i].annotations[a].colour != java.awt.Color.black)
1375 ae.setColour(aa[i].annotations[a].colour.getRGB());
1378 an.addAnnotationElement(ae);
1379 if (aa[i].autoCalculated)
1381 // only write one non-null entry into the annotation row -
1382 // sufficient to get the visualization attributes necessary to
1390 an.setScoreOnly(true);
1392 if (!storeDS || (storeDS && !aa[i].autoCalculated))
1394 // skip autocalculated annotation - these are only provided for
1396 vamsasSet.addAnnotation(an);
1402 private CalcIdParam createCalcIdParam(String calcId, AlignViewport av)
1404 AutoCalcSetting settings = av.getCalcIdSettingsFor(calcId);
1405 if (settings != null)
1407 CalcIdParam vCalcIdParam = new CalcIdParam();
1408 vCalcIdParam.setCalcId(calcId);
1409 vCalcIdParam.addServiceURL(settings.getServiceURI());
1410 // generic URI allowing a third party to resolve another instance of the
1411 // service used for this calculation
1412 for (String urls : settings.getServiceURLs())
1414 vCalcIdParam.addServiceURL(urls);
1416 vCalcIdParam.setVersion("1.0");
1417 if (settings.getPreset() != null)
1419 WsParamSetI setting = settings.getPreset();
1420 vCalcIdParam.setName(setting.getName());
1421 vCalcIdParam.setDescription(setting.getDescription());
1425 vCalcIdParam.setName("");
1426 vCalcIdParam.setDescription("Last used parameters");
1428 // need to be able to recover 1) settings 2) user-defined presets or
1429 // recreate settings from preset 3) predefined settings provided by
1430 // service - or settings that can be transferred (or discarded)
1431 vCalcIdParam.setParameters(settings.getWsParamFile().replace("\n",
1433 vCalcIdParam.setAutoUpdate(settings.isAutoUpdate());
1434 // todo - decide if updateImmediately is needed for any projects.
1436 return vCalcIdParam;
1441 private boolean recoverCalcIdParam(CalcIdParam calcIdParam,
1444 if (calcIdParam.getVersion().equals("1.0"))
1446 Jws2Instance service = Jws2Discoverer.getDiscoverer()
1447 .getPreferredServiceFor(calcIdParam.getServiceURL());
1448 if (service != null)
1450 WsParamSetI parmSet = null;
1453 parmSet = service.getParamStore().parseServiceParameterFile(
1454 calcIdParam.getName(), calcIdParam.getDescription(),
1455 calcIdParam.getServiceURL(),
1456 calcIdParam.getParameters().replace("|\\n|", "\n"));
1457 } catch (IOException x)
1459 warn("Couldn't parse parameter data for "
1460 + calcIdParam.getCalcId(), x);
1463 List<ArgumentI> argList = null;
1464 if (calcIdParam.getName().length() > 0)
1466 parmSet = service.getParamStore()
1467 .getPreset(calcIdParam.getName());
1468 if (parmSet != null)
1470 // TODO : check we have a good match with settings in AACon -
1471 // otherwise we'll need to create a new preset
1476 argList = parmSet.getArguments();
1479 AAConSettings settings = new AAConSettings(
1480 calcIdParam.isAutoUpdate(), service, parmSet, argList);
1481 av.setCalcIdSettingsFor(calcIdParam.getCalcId(), settings,
1482 calcIdParam.isNeedsUpdate());
1487 warn("Cannot resolve a service for the parameters used in this project. Try configuring a JABAWS server.");
1491 throw new Error("Unsupported Version for calcIdparam "
1492 + calcIdParam.toString());
1496 * External mapping between jalview objects and objects yielding a valid and
1497 * unique object ID string. This is null for normal Jalview project IO, but
1498 * non-null when a jalview project is being read or written as part of a
1501 IdentityHashMap jv2vobj = null;
1504 * Construct a unique ID for jvobj using either existing bindings or if none
1505 * exist, the result of the hashcode call for the object.
1508 * jalview data object
1509 * @return unique ID for referring to jvobj
1511 private String makeHashCode(Object jvobj, String altCode)
1513 if (jv2vobj != null)
1515 Object id = jv2vobj.get(jvobj);
1518 return id.toString();
1520 // check string ID mappings
1521 if (jvids2vobj != null && jvobj instanceof String)
1523 id = jvids2vobj.get(jvobj);
1527 return id.toString();
1529 // give up and warn that something has gone wrong
1530 warn("Cannot find ID for object in external mapping : " + jvobj);
1536 * return local jalview object mapped to ID, if it exists
1540 * @return null or object bound to idcode
1542 private Object retrieveExistingObj(String idcode)
1544 if (idcode != null && vobj2jv != null)
1546 return vobj2jv.get(idcode);
1552 * binding from ID strings from external mapping table to jalview data model
1555 private Hashtable vobj2jv;
1557 private Sequence createVamsasSequence(String id, SequenceI jds)
1559 return createVamsasSequence(true, id, jds, null);
1562 private Sequence createVamsasSequence(boolean recurse, String id,
1563 SequenceI jds, SequenceI parentseq)
1565 Sequence vamsasSeq = new Sequence();
1566 vamsasSeq.setId(id);
1567 vamsasSeq.setName(jds.getName());
1568 vamsasSeq.setSequence(jds.getSequenceAsString());
1569 vamsasSeq.setDescription(jds.getDescription());
1570 jalview.datamodel.DBRefEntry[] dbrefs = null;
1571 if (jds.getDatasetSequence() != null)
1573 vamsasSeq.setDsseqid(seqHash(jds.getDatasetSequence()));
1574 if (jds.getDatasetSequence().getDBRef() != null)
1576 dbrefs = jds.getDatasetSequence().getDBRef();
1581 vamsasSeq.setDsseqid(id); // so we can tell which sequences really are
1582 // dataset sequences only
1583 dbrefs = jds.getDBRef();
1587 for (int d = 0; d < dbrefs.length; d++)
1589 DBRef dbref = new DBRef();
1590 dbref.setSource(dbrefs[d].getSource());
1591 dbref.setVersion(dbrefs[d].getVersion());
1592 dbref.setAccessionId(dbrefs[d].getAccessionId());
1593 if (dbrefs[d].hasMap())
1595 Mapping mp = createVamsasMapping(dbrefs[d].getMap(), parentseq,
1597 dbref.setMapping(mp);
1599 vamsasSeq.addDBRef(dbref);
1605 private Mapping createVamsasMapping(jalview.datamodel.Mapping jmp,
1606 SequenceI parentseq, SequenceI jds, boolean recurse)
1609 if (jmp.getMap() != null)
1613 jalview.util.MapList mlst = jmp.getMap();
1614 int r[] = mlst.getFromRanges();
1615 for (int s = 0; s < r.length; s += 2)
1617 MapListFrom mfrom = new MapListFrom();
1618 mfrom.setStart(r[s]);
1619 mfrom.setEnd(r[s + 1]);
1620 mp.addMapListFrom(mfrom);
1622 r = mlst.getToRanges();
1623 for (int s = 0; s < r.length; s += 2)
1625 MapListTo mto = new MapListTo();
1627 mto.setEnd(r[s + 1]);
1628 mp.addMapListTo(mto);
1630 mp.setMapFromUnit(mlst.getFromRatio());
1631 mp.setMapToUnit(mlst.getToRatio());
1632 if (jmp.getTo() != null)
1634 MappingChoice mpc = new MappingChoice();
1636 && (parentseq != jmp.getTo() || parentseq
1637 .getDatasetSequence() != jmp.getTo()))
1639 mpc.setSequence(createVamsasSequence(false, seqHash(jmp.getTo()),
1645 SequenceI ps = null;
1646 if (parentseq != jmp.getTo()
1647 && parentseq.getDatasetSequence() != jmp.getTo())
1649 // chaining dbref rather than a handshaking one
1650 jmpid = seqHash(ps = jmp.getTo());
1654 jmpid = seqHash(ps = parentseq);
1656 mpc.setDseqFor(jmpid);
1657 if (!seqRefIds.containsKey(mpc.getDseqFor()))
1659 jalview.bin.Cache.log.debug("creatign new DseqFor ID");
1660 seqRefIds.put(mpc.getDseqFor(), ps);
1664 jalview.bin.Cache.log.debug("reusing DseqFor ID");
1667 mp.setMappingChoice(mpc);
1673 String SetUserColourScheme(jalview.schemes.ColourSchemeI cs,
1674 Vector userColours, JalviewModelSequence jms)
1677 jalview.schemes.UserColourScheme ucs = (jalview.schemes.UserColourScheme) cs;
1678 boolean newucs = false;
1679 if (!userColours.contains(ucs))
1681 userColours.add(ucs);
1684 id = "ucs" + userColours.indexOf(ucs);
1687 // actually create the scheme's entry in the XML model
1688 java.awt.Color[] colours = ucs.getColours();
1689 jalview.schemabinding.version2.UserColours uc = new jalview.schemabinding.version2.UserColours();
1690 jalview.schemabinding.version2.UserColourScheme jbucs = new jalview.schemabinding.version2.UserColourScheme();
1692 for (int i = 0; i < colours.length; i++)
1694 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
1695 col.setName(ResidueProperties.aa[i]);
1696 col.setRGB(jalview.util.Format.getHexString(colours[i]));
1697 jbucs.addColour(col);
1699 if (ucs.getLowerCaseColours() != null)
1701 colours = ucs.getLowerCaseColours();
1702 for (int i = 0; i < colours.length; i++)
1704 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
1705 col.setName(ResidueProperties.aa[i].toLowerCase());
1706 col.setRGB(jalview.util.Format.getHexString(colours[i]));
1707 jbucs.addColour(col);
1712 uc.setUserColourScheme(jbucs);
1713 jms.addUserColours(uc);
1719 jalview.schemes.UserColourScheme GetUserColourScheme(
1720 JalviewModelSequence jms, String id)
1722 UserColours[] uc = jms.getUserColours();
1723 UserColours colours = null;
1725 for (int i = 0; i < uc.length; i++)
1727 if (uc[i].getId().equals(id))
1735 java.awt.Color[] newColours = new java.awt.Color[24];
1737 for (int i = 0; i < 24; i++)
1739 newColours[i] = new java.awt.Color(Integer.parseInt(colours
1740 .getUserColourScheme().getColour(i).getRGB(), 16));
1743 jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme(
1746 if (colours.getUserColourScheme().getColourCount() > 24)
1748 newColours = new java.awt.Color[23];
1749 for (int i = 0; i < 23; i++)
1751 newColours[i] = new java.awt.Color(Integer.parseInt(colours
1752 .getUserColourScheme().getColour(i + 24).getRGB(), 16));
1754 ucs.setLowerCaseColours(newColours);
1761 * contains last error message (if any) encountered by XML loader.
1763 String errorMessage = null;
1766 * flag to control whether the Jalview2XML_V1 parser should be deferred to if
1767 * exceptions are raised during project XML parsing
1769 public boolean attemptversion1parse = true;
1772 * Load a jalview project archive from a jar file
1775 * - HTTP URL or filename
1777 public AlignFrame LoadJalviewAlign(final String file)
1780 jalview.gui.AlignFrame af = null;
1784 // create list to store references for any new Jmol viewers created
1785 newStructureViewers = new Vector<AppJmol>();
1786 // UNMARSHALLER SEEMS TO CLOSE JARINPUTSTREAM, MOST ANNOYING
1787 // Workaround is to make sure caller implements the JarInputStreamProvider
1789 // so we can re-open the jar input stream for each entry.
1791 jarInputStreamProvider jprovider = createjarInputStreamProvider(file);
1792 af = LoadJalviewAlign(jprovider);
1794 } catch (MalformedURLException e)
1796 errorMessage = "Invalid URL format for '" + file + "'";
1802 SwingUtilities.invokeAndWait(new Runnable()
1806 setLoadingFinishedForNewStructureViewers();
1809 } catch (Exception x)
1817 private jarInputStreamProvider createjarInputStreamProvider(
1818 final String file) throws MalformedURLException
1821 errorMessage = null;
1822 uniqueSetSuffix = null;
1824 viewportsAdded = null;
1825 frefedSequence = null;
1827 if (file.startsWith("http://"))
1829 url = new URL(file);
1831 final URL _url = url;
1832 return new jarInputStreamProvider()
1836 public JarInputStream getJarInputStream() throws IOException
1840 return new JarInputStream(_url.openStream());
1844 return new JarInputStream(new FileInputStream(file));
1849 public String getFilename()
1857 * Recover jalview session from a jalview project archive. Caller may
1858 * initialise uniqueSetSuffix, seqRefIds, viewportsAdded and frefedSequence
1859 * themselves. Any null fields will be initialised with default values,
1860 * non-null fields are left alone.
1865 public AlignFrame LoadJalviewAlign(final jarInputStreamProvider jprovider)
1867 errorMessage = null;
1868 if (uniqueSetSuffix == null)
1870 uniqueSetSuffix = System.currentTimeMillis() % 100000 + "";
1872 if (seqRefIds == null)
1874 seqRefIds = new Hashtable();
1876 if (viewportsAdded == null)
1878 viewportsAdded = new Hashtable();
1880 if (frefedSequence == null)
1882 frefedSequence = new Vector();
1885 jalview.gui.AlignFrame af = null, _af = null;
1886 Hashtable gatherToThisFrame = new Hashtable();
1887 final String file = jprovider.getFilename();
1890 JarInputStream jin = null;
1891 JarEntry jarentry = null;
1896 jin = jprovider.getJarInputStream();
1897 for (int i = 0; i < entryCount; i++)
1899 jarentry = jin.getNextJarEntry();
1902 if (jarentry != null && jarentry.getName().endsWith(".xml"))
1904 InputStreamReader in = new InputStreamReader(jin, "UTF-8");
1905 JalviewModel object = new JalviewModel();
1907 Unmarshaller unmar = new Unmarshaller(object);
1908 unmar.setValidation(false);
1909 object = (JalviewModel) unmar.unmarshal(in);
1910 if (true) // !skipViewport(object))
1912 _af = LoadFromObject(object, file, true, jprovider);
1913 if (object.getJalviewModelSequence().getViewportCount() > 0)
1916 if (object.getJalviewModelSequence().getViewportCount() > 1
1917 && af.viewport.gatherViewsHere)
1919 gatherToThisFrame.put(af.viewport.getSequenceSetId(), af);
1925 else if (jarentry != null)
1927 // Some other file here.
1930 } while (jarentry != null);
1931 resolveFrefedSequences();
1932 } catch (java.io.FileNotFoundException ex)
1934 ex.printStackTrace();
1935 errorMessage = "Couldn't locate Jalview XML file : " + file;
1936 System.err.println("Exception whilst loading jalview XML file : "
1938 } catch (java.net.UnknownHostException ex)
1940 ex.printStackTrace();
1941 errorMessage = "Couldn't locate Jalview XML file : " + file;
1942 System.err.println("Exception whilst loading jalview XML file : "
1944 } catch (Exception ex)
1946 System.err.println("Parsing as Jalview Version 2 file failed.");
1947 ex.printStackTrace(System.err);
1948 if (attemptversion1parse)
1950 // Is Version 1 Jar file?
1953 af = new Jalview2XML_V1(raiseGUI).LoadJalviewAlign(jprovider);
1954 } catch (Exception ex2)
1956 System.err.println("Exception whilst loading as jalviewXMLV1:");
1957 ex2.printStackTrace();
1961 if (Desktop.instance != null)
1963 Desktop.instance.stopLoading();
1967 System.out.println("Successfully loaded archive file");
1970 ex.printStackTrace();
1972 System.err.println("Exception whilst loading jalview XML file : "
1974 } catch (OutOfMemoryError e)
1976 // Don't use the OOM Window here
1977 errorMessage = "Out of memory loading jalview XML file";
1978 System.err.println("Out of memory whilst loading jalview XML file");
1979 e.printStackTrace();
1982 if (Desktop.instance != null)
1984 Desktop.instance.stopLoading();
1987 Enumeration en = gatherToThisFrame.elements();
1988 while (en.hasMoreElements())
1990 Desktop.instance.gatherViews((AlignFrame) en.nextElement());
1992 if (errorMessage != null)
2000 * check errorMessage for a valid error message and raise an error box in the
2001 * GUI or write the current errorMessage to stderr and then clear the error
2004 protected void reportErrors()
2006 reportErrors(false);
2009 protected void reportErrors(final boolean saving)
2011 if (errorMessage != null)
2013 final String finalErrorMessage = errorMessage;
2016 javax.swing.SwingUtilities.invokeLater(new Runnable()
2021 JOptionPane.showInternalMessageDialog(Desktop.desktop,
2022 finalErrorMessage, "Error "
2023 + (saving ? "saving" : "loading")
2024 + " Jalview file", JOptionPane.WARNING_MESSAGE);
2030 System.err.println("Problem loading Jalview file: " + errorMessage);
2033 errorMessage = null;
2036 Hashtable alreadyLoadedPDB;
2039 * when set, local views will be updated from view stored in JalviewXML
2040 * Currently (28th Sep 2008) things will go horribly wrong in vamsas document
2041 * sync if this is set to true.
2043 private final boolean updateLocalViews = false;
2045 String loadPDBFile(jarInputStreamProvider jprovider, String pdbId)
2047 if (alreadyLoadedPDB == null)
2048 alreadyLoadedPDB = new Hashtable();
2050 if (alreadyLoadedPDB.containsKey(pdbId))
2051 return alreadyLoadedPDB.get(pdbId).toString();
2055 JarInputStream jin = jprovider.getJarInputStream();
2057 * if (jprovider.startsWith("http://")) { jin = new JarInputStream(new
2058 * URL(jprovider).openStream()); } else { jin = new JarInputStream(new
2059 * FileInputStream(jprovider)); }
2062 JarEntry entry = null;
2065 entry = jin.getNextJarEntry();
2066 } while (entry != null && !entry.getName().equals(pdbId));
2069 BufferedReader in = new BufferedReader(new InputStreamReader(jin));
2070 File outFile = File.createTempFile("jalview_pdb", ".txt");
2071 outFile.deleteOnExit();
2072 PrintWriter out = new PrintWriter(new FileOutputStream(outFile));
2075 while ((data = in.readLine()) != null)
2082 } catch (Exception foo)
2087 String t = outFile.getAbsolutePath();
2088 alreadyLoadedPDB.put(pdbId, t);
2093 warn("Couldn't find PDB file entry in Jalview Jar for " + pdbId);
2095 } catch (Exception ex)
2097 ex.printStackTrace();
2103 private class JvAnnotRow
2105 public JvAnnotRow(int i, AlignmentAnnotation jaa)
2112 * persisted version of annotation row from which to take vis properties
2114 public jalview.datamodel.AlignmentAnnotation template;
2117 * original position of the annotation row in the alignment
2123 * Load alignment frame from jalview XML DOM object
2128 * filename source string
2129 * @param loadTreesAndStructures
2130 * when false only create Viewport
2132 * data source provider
2133 * @return alignment frame created from view stored in DOM
2135 AlignFrame LoadFromObject(JalviewModel object, String file,
2136 boolean loadTreesAndStructures, jarInputStreamProvider jprovider)
2138 SequenceSet vamsasSet = object.getVamsasModel().getSequenceSet(0);
2139 Sequence[] vamsasSeq = vamsasSet.getSequence();
2141 JalviewModelSequence jms = object.getJalviewModelSequence();
2143 Viewport view = (jms.getViewportCount() > 0) ? jms.getViewport(0)
2146 // ////////////////////////////////
2149 Vector hiddenSeqs = null;
2150 jalview.datamodel.Sequence jseq;
2152 ArrayList tmpseqs = new ArrayList();
2154 boolean multipleView = false;
2156 JSeq[] JSEQ = object.getJalviewModelSequence().getJSeq();
2157 int vi = 0; // counter in vamsasSeq array
2158 for (int i = 0; i < JSEQ.length; i++)
2160 String seqId = JSEQ[i].getId();
2162 if (seqRefIds.get(seqId) != null)
2164 tmpseqs.add(seqRefIds.get(seqId));
2165 multipleView = true;
2169 jseq = new jalview.datamodel.Sequence(vamsasSeq[vi].getName(),
2170 vamsasSeq[vi].getSequence());
2171 jseq.setDescription(vamsasSeq[vi].getDescription());
2172 jseq.setStart(JSEQ[i].getStart());
2173 jseq.setEnd(JSEQ[i].getEnd());
2174 jseq.setVamsasId(uniqueSetSuffix + seqId);
2175 seqRefIds.put(vamsasSeq[vi].getId(), jseq);
2180 if (JSEQ[i].getHidden())
2182 if (hiddenSeqs == null)
2184 hiddenSeqs = new Vector();
2187 hiddenSeqs.addElement(seqRefIds.get(seqId));
2193 // Create the alignment object from the sequence set
2194 // ///////////////////////////////
2195 jalview.datamodel.Sequence[] orderedSeqs = new jalview.datamodel.Sequence[tmpseqs
2198 tmpseqs.toArray(orderedSeqs);
2200 jalview.datamodel.Alignment al = new jalview.datamodel.Alignment(
2203 // / Add the alignment properties
2204 for (int i = 0; i < vamsasSet.getSequenceSetPropertiesCount(); i++)
2206 SequenceSetProperties ssp = vamsasSet.getSequenceSetProperties(i);
2207 al.setProperty(ssp.getKey(), ssp.getValue());
2211 // SequenceFeatures are added to the DatasetSequence,
2212 // so we must create or recover the dataset before loading features
2213 // ///////////////////////////////
2214 if (vamsasSet.getDatasetId() == null || vamsasSet.getDatasetId() == "")
2216 // older jalview projects do not have a dataset id.
2217 al.setDataset(null);
2221 recoverDatasetFor(vamsasSet, al);
2223 // ///////////////////////////////
2225 Hashtable pdbloaded = new Hashtable();
2228 // load sequence features, database references and any associated PDB
2229 // structures for the alignment
2230 for (int i = 0; i < vamsasSeq.length; i++)
2232 if (JSEQ[i].getFeaturesCount() > 0)
2234 Features[] features = JSEQ[i].getFeatures();
2235 for (int f = 0; f < features.length; f++)
2237 jalview.datamodel.SequenceFeature sf = new jalview.datamodel.SequenceFeature(
2238 features[f].getType(), features[f].getDescription(),
2239 features[f].getStatus(), features[f].getBegin(),
2240 features[f].getEnd(), features[f].getFeatureGroup());
2242 sf.setScore(features[f].getScore());
2243 for (int od = 0; od < features[f].getOtherDataCount(); od++)
2245 OtherData keyValue = features[f].getOtherData(od);
2246 if (keyValue.getKey().startsWith("LINK"))
2248 sf.addLink(keyValue.getValue());
2252 sf.setValue(keyValue.getKey(), keyValue.getValue());
2257 al.getSequenceAt(i).getDatasetSequence().addSequenceFeature(sf);
2260 if (vamsasSeq[i].getDBRefCount() > 0)
2262 addDBRefs(al.getSequenceAt(i).getDatasetSequence(), vamsasSeq[i]);
2264 if (JSEQ[i].getPdbidsCount() > 0)
2266 Pdbids[] ids = JSEQ[i].getPdbids();
2267 for (int p = 0; p < ids.length; p++)
2269 jalview.datamodel.PDBEntry entry = new jalview.datamodel.PDBEntry();
2270 entry.setId(ids[p].getId());
2271 entry.setType(ids[p].getType());
2272 if (ids[p].getFile() != null)
2274 if (!pdbloaded.containsKey(ids[p].getFile()))
2276 entry.setFile(loadPDBFile(jprovider, ids[p].getId()));
2280 entry.setFile(pdbloaded.get(ids[p].getId()).toString());
2284 al.getSequenceAt(i).getDatasetSequence().addPDBId(entry);
2288 } // end !multipleview
2290 // ///////////////////////////////
2291 // LOAD SEQUENCE MAPPINGS
2293 if (vamsasSet.getAlcodonFrameCount() > 0)
2295 // TODO Potentially this should only be done once for all views of an
2297 AlcodonFrame[] alc = vamsasSet.getAlcodonFrame();
2298 for (int i = 0; i < alc.length; i++)
2300 jalview.datamodel.AlignedCodonFrame cf = new jalview.datamodel.AlignedCodonFrame(
2301 alc[i].getAlcodonCount());
2302 if (alc[i].getAlcodonCount() > 0)
2304 Alcodon[] alcods = alc[i].getAlcodon();
2305 for (int p = 0; p < cf.codons.length; p++)
2307 if (alcods[p].hasPos1() && alcods[p].hasPos2()
2308 && alcods[p].hasPos3())
2310 // translated codons require three valid positions
2311 cf.codons[p] = new int[3];
2312 cf.codons[p][0] = (int) alcods[p].getPos1();
2313 cf.codons[p][1] = (int) alcods[p].getPos2();
2314 cf.codons[p][2] = (int) alcods[p].getPos3();
2318 cf.codons[p] = null;
2322 if (alc[i].getAlcodMapCount() > 0)
2324 AlcodMap[] maps = alc[i].getAlcodMap();
2325 for (int m = 0; m < maps.length; m++)
2327 SequenceI dnaseq = (SequenceI) seqRefIds
2328 .get(maps[m].getDnasq());
2330 jalview.datamodel.Mapping mapping = null;
2331 // attach to dna sequence reference.
2332 if (maps[m].getMapping() != null)
2334 mapping = addMapping(maps[m].getMapping());
2338 cf.addMap(dnaseq, mapping.getTo(), mapping.getMap());
2343 frefedSequence.add(new Object[]
2344 { maps[m].getDnasq(), cf, mapping });
2348 al.addCodonFrame(cf);
2353 // ////////////////////////////////
2355 ArrayList<JvAnnotRow> autoAlan = new ArrayList<JvAnnotRow>();
2357 * store any annotations which forward reference a group's ID
2359 Hashtable<String, ArrayList<jalview.datamodel.AlignmentAnnotation>> groupAnnotRefs = new Hashtable<String, ArrayList<jalview.datamodel.AlignmentAnnotation>>();
2361 if (vamsasSet.getAnnotationCount() > 0)
2363 Annotation[] an = vamsasSet.getAnnotation();
2365 for (int i = 0; i < an.length; i++)
2368 * test if annotation is automatically calculated for this view only
2370 boolean autoForView = false;
2371 if (an[i].getLabel().equals("Quality")
2372 || an[i].getLabel().equals("Conservation")
2373 || an[i].getLabel().equals("Consensus"))
2375 // Kludge for pre 2.5 projects which lacked the autocalculated flag
2377 if (!an[i].hasAutoCalculated())
2379 an[i].setAutoCalculated(true);
2383 || (an[i].hasAutoCalculated() && an[i].isAutoCalculated()))
2385 // remove ID - we don't recover annotation from other views for
2386 // view-specific annotation
2390 // set visiblity for other annotation in this view
2391 if (an[i].getId() != null
2392 && annotationIds.containsKey(an[i].getId()))
2394 jalview.datamodel.AlignmentAnnotation jda = (jalview.datamodel.AlignmentAnnotation) annotationIds
2395 .get(an[i].getId());
2396 // in principle Visible should always be true for annotation displayed
2397 // in multiple views
2398 if (an[i].hasVisible())
2399 jda.visible = an[i].getVisible();
2401 al.addAnnotation(jda);
2405 // Construct new annotation from model.
2406 AnnotationElement[] ae = an[i].getAnnotationElement();
2407 jalview.datamodel.Annotation[] anot = null;
2408 java.awt.Color firstColour = null;
2410 if (!an[i].getScoreOnly())
2412 anot = new jalview.datamodel.Annotation[al.getWidth()];
2413 for (int aa = 0; aa < ae.length && aa < anot.length; aa++)
2415 anpos = ae[aa].getPosition();
2417 if (anpos >= anot.length)
2420 anot[anpos] = new jalview.datamodel.Annotation(
2422 ae[aa].getDisplayCharacter(), ae[aa].getDescription(),
2423 (ae[aa].getSecondaryStructure() == null || ae[aa]
2424 .getSecondaryStructure().length() == 0) ? ' '
2425 : ae[aa].getSecondaryStructure().charAt(0),
2429 // JBPNote: Consider verifying dataflow for IO of secondary
2430 // structure annotation read from Stockholm files
2431 // this was added to try to ensure that
2432 // if (anot[ae[aa].getPosition()].secondaryStructure>' ')
2434 // anot[ae[aa].getPosition()].displayCharacter = "";
2436 anot[anpos].colour = new java.awt.Color(ae[aa].getColour());
2437 if (firstColour == null)
2439 firstColour = anot[anpos].colour;
2443 jalview.datamodel.AlignmentAnnotation jaa = null;
2445 if (an[i].getGraph())
2447 float llim = 0, hlim = 0;
2448 // if (autoForView || an[i].isAutoCalculated()) {
2451 jaa = new jalview.datamodel.AlignmentAnnotation(an[i].getLabel(),
2452 an[i].getDescription(), anot, llim, hlim,
2453 an[i].getGraphType());
2455 jaa.graphGroup = an[i].getGraphGroup();
2456 jaa._linecolour = firstColour;
2457 if (an[i].getThresholdLine() != null)
2459 jaa.setThreshold(new jalview.datamodel.GraphLine(an[i]
2460 .getThresholdLine().getValue(), an[i]
2461 .getThresholdLine().getLabel(), new java.awt.Color(
2462 an[i].getThresholdLine().getColour())));
2465 if (autoForView || an[i].isAutoCalculated())
2467 // Hardwire the symbol display line to ensure that labels for
2468 // histograms are displayed
2474 jaa = new jalview.datamodel.AlignmentAnnotation(an[i].getLabel(),
2475 an[i].getDescription(), anot);
2476 jaa._linecolour = firstColour;
2478 // register new annotation
2479 if (an[i].getId() != null)
2481 annotationIds.put(an[i].getId(), jaa);
2482 jaa.annotationId = an[i].getId();
2484 // recover sequence association
2485 if (an[i].getSequenceRef() != null)
2487 if (al.findName(an[i].getSequenceRef()) != null)
2489 jaa.createSequenceMapping(al.findName(an[i].getSequenceRef()),
2491 al.findName(an[i].getSequenceRef()).addAlignmentAnnotation(jaa);
2494 // and make a note of any group association
2495 if (an[i].getGroupRef() != null && an[i].getGroupRef().length() > 0)
2497 ArrayList<jalview.datamodel.AlignmentAnnotation> aal = groupAnnotRefs
2498 .get(an[i].getGroupRef());
2501 aal = new ArrayList<jalview.datamodel.AlignmentAnnotation>();
2502 groupAnnotRefs.put(an[i].getGroupRef(), aal);
2507 if (an[i].hasScore())
2509 jaa.setScore(an[i].getScore());
2511 if (an[i].hasVisible())
2512 jaa.visible = an[i].getVisible();
2514 if (an[i].hasCentreColLabels())
2515 jaa.centreColLabels = an[i].getCentreColLabels();
2517 if (an[i].hasScaleColLabels())
2519 jaa.scaleColLabel = an[i].getScaleColLabels();
2521 if (an[i].hasAutoCalculated() && an[i].isAutoCalculated())
2523 // newer files have an 'autoCalculated' flag and store calculation
2524 // state in viewport properties
2525 jaa.autoCalculated = true; // means annotation will be marked for
2526 // update at end of load.
2528 if (an[i].hasGraphHeight())
2530 jaa.graphHeight = an[i].getGraphHeight();
2532 if (an[i].hasBelowAlignment())
2534 jaa.belowAlignment = an[i].isBelowAlignment();
2536 jaa.setCalcId(an[i].getCalcId());
2538 if (jaa.autoCalculated)
2540 autoAlan.add(new JvAnnotRow(i, jaa));
2543 // if (!autoForView)
2545 // add autocalculated group annotation and any user created annotation
2547 al.addAnnotation(jaa);
2551 // ///////////////////////
2553 // Create alignment markup and styles for this view
2554 if (jms.getJGroupCount() > 0)
2556 JGroup[] groups = jms.getJGroup();
2558 for (int i = 0; i < groups.length; i++)
2560 ColourSchemeI cs = null;
2562 if (groups[i].getColour() != null)
2564 if (groups[i].getColour().startsWith("ucs"))
2566 cs = GetUserColourScheme(jms, groups[i].getColour());
2570 cs = ColourSchemeProperty.getColour(al, groups[i].getColour());
2575 cs.setThreshold(groups[i].getPidThreshold(), true);
2579 Vector seqs = new Vector();
2581 for (int s = 0; s < groups[i].getSeqCount(); s++)
2583 String seqId = groups[i].getSeq(s) + "";
2584 jalview.datamodel.SequenceI ts = (jalview.datamodel.SequenceI) seqRefIds
2589 seqs.addElement(ts);
2593 if (seqs.size() < 1)
2598 jalview.datamodel.SequenceGroup sg = new jalview.datamodel.SequenceGroup(
2599 seqs, groups[i].getName(), cs, groups[i].getDisplayBoxes(),
2600 groups[i].getDisplayText(), groups[i].getColourText(),
2601 groups[i].getStart(), groups[i].getEnd());
2603 sg.setOutlineColour(new java.awt.Color(groups[i].getOutlineColour()));
2605 sg.textColour = new java.awt.Color(groups[i].getTextCol1());
2606 sg.textColour2 = new java.awt.Color(groups[i].getTextCol2());
2607 sg.setShowNonconserved(groups[i].hasShowUnconserved() ? groups[i]
2608 .isShowUnconserved() : false);
2609 sg.thresholdTextColour = groups[i].getTextColThreshold();
2610 if (groups[i].hasShowConsensusHistogram())
2612 sg.setShowConsensusHistogram(groups[i].isShowConsensusHistogram());
2615 if (groups[i].hasShowSequenceLogo())
2617 sg.setshowSequenceLogo(groups[i].isShowSequenceLogo());
2619 if (groups[i].hasNormaliseSequenceLogo())
2621 sg.setNormaliseSequenceLogo(groups[i].isNormaliseSequenceLogo());
2623 if (groups[i].hasIgnoreGapsinConsensus())
2625 sg.setIgnoreGapsConsensus(groups[i].getIgnoreGapsinConsensus());
2627 if (groups[i].getConsThreshold() != 0)
2629 jalview.analysis.Conservation c = new jalview.analysis.Conservation(
2630 "All", ResidueProperties.propHash, 3,
2631 sg.getSequences(null), 0, sg.getWidth() - 1);
2633 c.verdict(false, 25);
2634 sg.cs.setConservation(c);
2637 if (groups[i].getId() != null && groupAnnotRefs.size() > 0)
2639 // re-instate unique group/annotation row reference
2640 ArrayList<jalview.datamodel.AlignmentAnnotation> jaal = groupAnnotRefs
2641 .get(groups[i].getId());
2644 for (jalview.datamodel.AlignmentAnnotation jaa : jaal)
2647 if (jaa.autoCalculated)
2649 // match up and try to set group autocalc alignment row for this
2651 if (jaa.label.startsWith("Consensus for "))
2653 sg.setConsensus(jaa);
2655 // match up and try to set group autocalc alignment row for this
2657 if (jaa.label.startsWith("Conservation for "))
2659 sg.setConservationRow(jaa);
2671 // only dataset in this model, so just return.
2674 // ///////////////////////////////
2677 // If we just load in the same jar file again, the sequenceSetId
2678 // will be the same, and we end up with multiple references
2679 // to the same sequenceSet. We must modify this id on load
2680 // so that each load of the file gives a unique id
2681 String uniqueSeqSetId = view.getSequenceSetId() + uniqueSetSuffix;
2682 String viewId = (view.getId() == null ? null : view.getId()
2684 AlignFrame af = null;
2685 AlignViewport av = null;
2686 // now check to see if we really need to create a new viewport.
2687 if (multipleView && viewportsAdded.size() == 0)
2689 // We recovered an alignment for which a viewport already exists.
2690 // TODO: fix up any settings necessary for overlaying stored state onto
2691 // state recovered from another document. (may not be necessary).
2692 // we may need a binding from a viewport in memory to one recovered from
2694 // and then recover its containing af to allow the settings to be applied.
2695 // TODO: fix for vamsas demo
2697 .println("About to recover a viewport for existing alignment: Sequence set ID is "
2699 Object seqsetobj = retrieveExistingObj(uniqueSeqSetId);
2700 if (seqsetobj != null)
2702 if (seqsetobj instanceof String)
2704 uniqueSeqSetId = (String) seqsetobj;
2706 .println("Recovered extant sequence set ID mapping for ID : New Sequence set ID is "
2712 .println("Warning : Collision between sequence set ID string and existing jalview object mapping.");
2717 AlignmentPanel ap = null;
2718 boolean isnewview = true;
2721 // Check to see if this alignment already has a view id == viewId
2722 jalview.gui.AlignmentPanel views[] = Desktop
2723 .getAlignmentPanels(uniqueSeqSetId);
2724 if (views != null && views.length > 0)
2726 for (int v = 0; v < views.length; v++)
2728 if (views[v].av.getViewId().equalsIgnoreCase(viewId))
2730 // recover the existing alignpanel, alignframe, viewport
2731 af = views[v].alignFrame;
2734 // TODO: could even skip resetting view settings if we don't want to
2735 // change the local settings from other jalview processes
2744 af = loadViewport(file, JSEQ, hiddenSeqs, al, jms, view,
2745 uniqueSeqSetId, viewId, autoAlan);
2750 // /////////////////////////////////////
2751 if (loadTreesAndStructures && jms.getTreeCount() > 0)
2755 for (int t = 0; t < jms.getTreeCount(); t++)
2758 Tree tree = jms.getTree(t);
2760 TreePanel tp = (TreePanel) retrieveExistingObj(tree.getId());
2763 tp = af.ShowNewickTree(
2764 new jalview.io.NewickFile(tree.getNewick()),
2765 tree.getTitle(), tree.getWidth(), tree.getHeight(),
2766 tree.getXpos(), tree.getYpos());
2767 if (tree.getId() != null)
2769 // perhaps bind the tree id to something ?
2774 // update local tree attributes ?
2775 // TODO: should check if tp has been manipulated by user - if so its
2776 // settings shouldn't be modified
2777 tp.setTitle(tree.getTitle());
2778 tp.setBounds(new Rectangle(tree.getXpos(), tree.getYpos(), tree
2779 .getWidth(), tree.getHeight()));
2780 tp.av = av; // af.viewport; // TODO: verify 'associate with all
2783 tp.treeCanvas.av = av; // af.viewport;
2784 tp.treeCanvas.ap = ap; // af.alignPanel;
2789 warn("There was a problem recovering stored Newick tree: \n"
2790 + tree.getNewick());
2794 tp.fitToWindow.setState(tree.getFitToWindow());
2795 tp.fitToWindow_actionPerformed(null);
2797 if (tree.getFontName() != null)
2799 tp.setTreeFont(new java.awt.Font(tree.getFontName(), tree
2800 .getFontStyle(), tree.getFontSize()));
2804 tp.setTreeFont(new java.awt.Font(view.getFontName(), view
2805 .getFontStyle(), tree.getFontSize()));
2808 tp.showPlaceholders(tree.getMarkUnlinked());
2809 tp.showBootstrap(tree.getShowBootstrap());
2810 tp.showDistances(tree.getShowDistances());
2812 tp.treeCanvas.threshold = tree.getThreshold();
2814 if (tree.getCurrentTree())
2816 af.viewport.setCurrentTree(tp.getTree());
2820 } catch (Exception ex)
2822 ex.printStackTrace();
2826 // //LOAD STRUCTURES
2827 if (loadTreesAndStructures)
2829 // run through all PDB ids on the alignment, and collect mappings between
2830 // jmol view ids and all sequences referring to it
2831 Hashtable<String, Object[]> jmolViewIds = new Hashtable();
2833 for (int i = 0; i < JSEQ.length; i++)
2835 if (JSEQ[i].getPdbidsCount() > 0)
2837 Pdbids[] ids = JSEQ[i].getPdbids();
2838 for (int p = 0; p < ids.length; p++)
2840 for (int s = 0; s < ids[p].getStructureStateCount(); s++)
2842 // check to see if we haven't already created this structure view
2843 String sviewid = (ids[p].getStructureState(s).getViewId() == null) ? null
2844 : ids[p].getStructureState(s).getViewId()
2846 jalview.datamodel.PDBEntry jpdb = new jalview.datamodel.PDBEntry();
2847 // Originally : ids[p].getFile()
2848 // : TODO: verify external PDB file recovery still works in normal
2849 // jalview project load
2850 jpdb.setFile(loadPDBFile(jprovider, ids[p].getId()));
2851 jpdb.setId(ids[p].getId());
2853 int x = ids[p].getStructureState(s).getXpos();
2854 int y = ids[p].getStructureState(s).getYpos();
2855 int width = ids[p].getStructureState(s).getWidth();
2856 int height = ids[p].getStructureState(s).getHeight();
2858 // Probably don't need to do this anymore...
2859 // Desktop.desktop.getComponentAt(x, y);
2860 // TODO: NOW: check that this recovers the PDB file correctly.
2861 String pdbFile = loadPDBFile(jprovider, ids[p].getId());
2862 jalview.datamodel.SequenceI seq = (jalview.datamodel.SequenceI) seqRefIds
2863 .get(JSEQ[i].getId() + "");
2864 if (sviewid == null)
2866 sviewid = "_jalview_pre2_4_" + x + "," + y + "," + width
2869 if (!jmolViewIds.containsKey(sviewid))
2871 jmolViewIds.put(sviewid, new Object[]
2873 { x, y, width, height }, "",
2874 new Hashtable<String, Object[]>(), new boolean[]
2875 { false, false, true } });
2876 // Legacy pre-2.7 conversion JAL-823 :
2877 // do not assume any view has to be linked for colour by
2881 // assemble String[] { pdb files }, String[] { id for each
2882 // file }, orig_fileloc, SequenceI[][] {{ seqs_file 1 }, {
2883 // seqs_file 2}, boolean[] {
2884 // linkAlignPanel,superposeWithAlignpanel}} from hash
2885 Object[] jmoldat = jmolViewIds.get(sviewid);
2886 ((boolean[]) jmoldat[3])[0] |= ids[p].getStructureState(s)
2887 .hasAlignwithAlignPanel() ? ids[p].getStructureState(
2888 s).getAlignwithAlignPanel() : false;
2889 // never colour by linked panel if not specified
2890 ((boolean[]) jmoldat[3])[1] |= ids[p].getStructureState(s)
2891 .hasColourwithAlignPanel() ? ids[p]
2892 .getStructureState(s).getColourwithAlignPanel()
2894 // default for pre-2.7 projects is that Jmol colouring is enabled
2895 ((boolean[]) jmoldat[3])[2] &= ids[p].getStructureState(s)
2896 .hasColourByJmol() ? ids[p].getStructureState(s)
2897 .getColourByJmol() : true;
2899 if (((String) jmoldat[1]).length() < ids[p]
2900 .getStructureState(s).getContent().length())
2903 jmoldat[1] = ids[p].getStructureState(s).getContent();
2906 if (ids[p].getFile() != null)
2908 File mapkey = new File(ids[p].getFile());
2909 Object[] seqstrmaps = (Object[]) ((Hashtable) jmoldat[2])
2911 if (seqstrmaps == null)
2913 ((Hashtable) jmoldat[2]).put(mapkey,
2914 seqstrmaps = new Object[]
2915 { pdbFile, ids[p].getId(), new Vector(),
2918 if (!((Vector) seqstrmaps[2]).contains(seq))
2920 ((Vector) seqstrmaps[2]).addElement(seq);
2921 // ((Vector)seqstrmaps[3]).addElement(n) :
2922 // in principle, chains
2923 // should be stored here : do we need to
2924 // TODO: store and recover seq/pdb_id :
2930 errorMessage = ("The Jmol views in this project were imported\nfrom an older version of Jalview.\nPlease review the sequence colour associations\nin the Colour by section of the Jmol View menu.\n\nIn the case of problems, see note at\nhttp://issues.jalview.org/browse/JAL-747");
2939 // Instantiate the associated Jmol views
2940 for (Entry<String, Object[]> entry : jmolViewIds.entrySet())
2942 String sviewid = entry.getKey();
2943 Object[] svattrib = entry.getValue();
2944 int[] geom = (int[]) svattrib[0];
2945 String state = (String) svattrib[1];
2946 Hashtable<File, Object[]> oldFiles = (Hashtable<File, Object[]>) svattrib[2];
2947 final boolean useinJmolsuperpos = ((boolean[]) svattrib[3])[0], usetoColourbyseq = ((boolean[]) svattrib[3])[1], jmolColouring = ((boolean[]) svattrib[3])[2];
2948 int x = geom[0], y = geom[1], width = geom[2], height = geom[3];
2949 // collate the pdbfile -> sequence mappings from this view
2950 Vector<String> pdbfilenames = new Vector<String>();
2951 Vector<SequenceI[]> seqmaps = new Vector<SequenceI[]>();
2952 Vector<String> pdbids = new Vector<String>();
2954 // Search to see if we've already created this Jmol view
2955 AppJmol comp = null;
2956 JInternalFrame[] frames = null;
2961 frames = Desktop.desktop.getAllFrames();
2962 } catch (ArrayIndexOutOfBoundsException e)
2964 // occasional No such child exceptions are thrown here...
2969 } catch (Exception f)
2974 } while (frames == null);
2975 // search for any Jmol windows already open from other
2976 // alignment views that exactly match the stored structure state
2977 for (int f = 0; comp == null && f < frames.length; f++)
2979 if (frames[f] instanceof AppJmol)
2982 && ((AppJmol) frames[f]).getViewId().equals(sviewid))
2984 // post jalview 2.4 schema includes structure view id
2985 comp = (AppJmol) frames[f];
2987 else if (frames[f].getX() == x && frames[f].getY() == y
2988 && frames[f].getHeight() == height
2989 && frames[f].getWidth() == width)
2991 comp = (AppJmol) frames[f];
2998 // create a new Jmol window.
2999 // First parse the Jmol state to translate filenames loaded into the
3000 // view, and record the order in which files are shown in the Jmol
3001 // view, so we can add the sequence mappings in same order.
3002 StringBuffer newFileLoc = null;
3003 int cp = 0, ncp, ecp;
3004 while ((ncp = state.indexOf("load ", cp)) > -1)
3006 if (newFileLoc == null)
3008 newFileLoc = new StringBuffer();
3012 // look for next filename in load statement
3013 newFileLoc.append(state.substring(cp,
3014 ncp = (state.indexOf("\"", ncp + 1) + 1)));
3015 String oldfilenam = state.substring(ncp,
3016 ecp = state.indexOf("\"", ncp));
3017 // recover the new mapping data for this old filename
3018 // have to normalize filename - since Jmol and jalview do
3020 // translation differently.
3021 Object[] filedat = oldFiles.get(new File(oldfilenam));
3022 newFileLoc.append(Platform
3023 .escapeString((String) filedat[0]));
3024 pdbfilenames.addElement((String) filedat[0]);
3025 pdbids.addElement((String) filedat[1]);
3026 seqmaps.addElement(((Vector<SequenceI>) filedat[2])
3027 .toArray(new SequenceI[0]));
3028 newFileLoc.append("\"");
3029 cp = ecp + 1; // advance beyond last \" and set cursor so we can
3030 // look for next file statement.
3031 } while ((ncp = state.indexOf("/*file*/", cp)) > -1);
3035 // just append rest of state
3036 newFileLoc.append(state.substring(cp));
3041 .print("Ignoring incomplete Jmol state for PDB ids: ");
3042 newFileLoc = new StringBuffer(state);
3043 newFileLoc.append("; load append ");
3044 for (File id : oldFiles.keySet())
3046 // add this and any other pdb files that should be present in
3048 Object[] filedat = oldFiles.get(id);
3050 newFileLoc.append(((String) filedat[0]));
3051 pdbfilenames.addElement((String) filedat[0]);
3052 pdbids.addElement((String) filedat[1]);
3053 seqmaps.addElement(((Vector<SequenceI>) filedat[2])
3054 .toArray(new SequenceI[0]));
3055 newFileLoc.append(" \"");
3056 newFileLoc.append((String) filedat[0]);
3057 newFileLoc.append("\"");
3060 newFileLoc.append(";");
3063 if (newFileLoc != null)
3065 int histbug = newFileLoc.indexOf("history = ");
3067 int diff = histbug == -1 ? -1 : newFileLoc.indexOf(";",
3069 String val = (diff == -1) ? null : newFileLoc.substring(
3071 if (val != null && val.length() >= 4)
3073 if (val.contains("e"))
3075 if (val.trim().equals("true"))
3083 newFileLoc.replace(histbug, diff, val);
3086 // TODO: assemble String[] { pdb files }, String[] { id for each
3087 // file }, orig_fileloc, SequenceI[][] {{ seqs_file 1 }, {
3088 // seqs_file 2}} from hash
3089 final String[] pdbf = pdbfilenames
3090 .toArray(new String[pdbfilenames.size()]), id = pdbids
3091 .toArray(new String[pdbids.size()]);
3092 final SequenceI[][] sq = seqmaps
3093 .toArray(new SequenceI[seqmaps.size()][]);
3094 final String fileloc = newFileLoc.toString(), vid = sviewid;
3095 final AlignFrame alf = af;
3096 final java.awt.Rectangle rect = new java.awt.Rectangle(x, y,
3100 javax.swing.SwingUtilities.invokeAndWait(new Runnable()
3105 AppJmol sview = null;
3108 sview = new AppJmol(pdbf, id, sq, alf.alignPanel,
3109 useinJmolsuperpos, usetoColourbyseq,
3110 jmolColouring, fileloc, rect, vid);
3111 addNewStructureViewer(sview);
3112 } catch (OutOfMemoryError ex)
3114 new OOMWarning("restoring structure view for PDB id "
3115 + id, (OutOfMemoryError) ex.getCause());
3116 if (sview != null && sview.isVisible())
3118 sview.closeViewer();
3119 sview.setVisible(false);
3125 } catch (InvocationTargetException ex)
3127 warn("Unexpected error when opening Jmol view.", ex);
3129 } catch (InterruptedException e)
3131 // e.printStackTrace();
3137 // if (comp != null)
3139 // NOTE: if the jalview project is part of a shared session then
3140 // view synchronization should/could be done here.
3142 // add mapping for sequences in this view to an already open Jmol
3144 for (File id : oldFiles.keySet())
3146 // add this and any other pdb files that should be present in the
3148 Object[] filedat = oldFiles.get(id);
3149 String pdbFile = (String) filedat[0];
3150 SequenceI[] seq = ((Vector<SequenceI>) filedat[2])
3151 .toArray(new SequenceI[0]);
3152 comp.jmb.ssm.setMapping(seq, null, pdbFile,
3153 jalview.io.AppletFormatAdapter.FILE);
3154 comp.jmb.addSequenceForStructFile(pdbFile, seq);
3156 // and add the AlignmentPanel's reference to the Jmol view
3157 comp.addAlignmentPanel(ap);
3158 if (useinJmolsuperpos)
3160 comp.useAlignmentPanelForSuperposition(ap);
3164 comp.excludeAlignmentPanelForSuperposition(ap);
3166 if (usetoColourbyseq)
3168 comp.useAlignmentPanelForColourbyseq(ap, !jmolColouring);
3172 comp.excludeAlignmentPanelForColourbyseq(ap);
3178 // and finally return.
3181 Vector<AppJmol> newStructureViewers=null;
3182 protected void addNewStructureViewer(AppJmol sview)
3184 if (newStructureViewers != null)
3186 sview.jmb.setFinishedLoadingFromArchive(false);
3187 newStructureViewers.add(sview);
3191 protected void setLoadingFinishedForNewStructureViewers()
3193 if (newStructureViewers != null)
3195 for (AppJmol sview : newStructureViewers)
3197 sview.jmb.setFinishedLoadingFromArchive(true);
3199 newStructureViewers.clear();
3200 newStructureViewers = null;
3204 AlignFrame loadViewport(String file, JSeq[] JSEQ, Vector hiddenSeqs,
3205 Alignment al, JalviewModelSequence jms, Viewport view,
3206 String uniqueSeqSetId, String viewId,
3207 ArrayList<JvAnnotRow> autoAlan)
3209 AlignFrame af = null;
3210 af = new AlignFrame(al, view.getWidth(), view.getHeight(),
3211 uniqueSeqSetId, viewId);
3213 af.setFileName(file, "Jalview");
3215 for (int i = 0; i < JSEQ.length; i++)
3217 af.viewport.setSequenceColour(af.viewport.getAlignment()
3218 .getSequenceAt(i), new java.awt.Color(JSEQ[i].getColour()));
3221 af.viewport.gatherViewsHere = view.getGatheredViews();
3223 if (view.getSequenceSetId() != null)
3225 jalview.gui.AlignViewport av = (jalview.gui.AlignViewport) viewportsAdded
3226 .get(uniqueSeqSetId);
3228 af.viewport.setSequenceSetId(uniqueSeqSetId);
3231 // propagate shared settings to this new view
3232 af.viewport.historyList = av.historyList;
3233 af.viewport.redoList = av.redoList;
3237 viewportsAdded.put(uniqueSeqSetId, af.viewport);
3239 // TODO: check if this method can be called repeatedly without
3240 // side-effects if alignpanel already registered.
3241 PaintRefresher.Register(af.alignPanel, uniqueSeqSetId);
3243 // apply Hidden regions to view.
3244 if (hiddenSeqs != null)
3246 for (int s = 0; s < JSEQ.length; s++)
3248 jalview.datamodel.SequenceGroup hidden = new jalview.datamodel.SequenceGroup();
3250 for (int r = 0; r < JSEQ[s].getHiddenSequencesCount(); r++)
3253 al.getSequenceAt(JSEQ[s].getHiddenSequences(r)), false);
3255 af.viewport.hideRepSequences(al.getSequenceAt(s), hidden);
3258 jalview.datamodel.SequenceI[] hseqs = new jalview.datamodel.SequenceI[hiddenSeqs
3261 for (int s = 0; s < hiddenSeqs.size(); s++)
3263 hseqs[s] = (jalview.datamodel.SequenceI) hiddenSeqs.elementAt(s);
3266 af.viewport.hideSequence(hseqs);
3269 // recover view properties and display parameters
3270 if (view.getViewName() != null)
3272 af.viewport.viewName = view.getViewName();
3273 af.setInitialTabVisible();
3275 af.setBounds(view.getXpos(), view.getYpos(), view.getWidth(),
3278 af.viewport.setShowAnnotation(view.getShowAnnotation());
3279 af.viewport.setAbovePIDThreshold(view.getPidSelected());
3281 af.viewport.setColourText(view.getShowColourText());
3283 af.viewport.setConservationSelected(view.getConservationSelected());
3284 af.viewport.setShowJVSuffix(view.getShowFullId());
3285 af.viewport.rightAlignIds = view.getRightAlignIds();
3286 af.viewport.setFont(new java.awt.Font(view.getFontName(), view
3287 .getFontStyle(), view.getFontSize()));
3288 af.alignPanel.fontChanged();
3289 af.viewport.setRenderGaps(view.getRenderGaps());
3290 af.viewport.setWrapAlignment(view.getWrapAlignment());
3291 af.alignPanel.setWrapAlignment(view.getWrapAlignment());
3292 af.viewport.setShowAnnotation(view.getShowAnnotation());
3293 af.alignPanel.setAnnotationVisible(view.getShowAnnotation());
3295 af.viewport.setShowBoxes(view.getShowBoxes());
3297 af.viewport.setShowText(view.getShowText());
3299 af.viewport.textColour = new java.awt.Color(view.getTextCol1());
3300 af.viewport.textColour2 = new java.awt.Color(view.getTextCol2());
3301 af.viewport.thresholdTextColour = view.getTextColThreshold();
3302 af.viewport.setShowUnconserved(view.hasShowUnconserved() ? view
3303 .isShowUnconserved() : false);
3304 af.viewport.setStartRes(view.getStartRes());
3305 af.viewport.setStartSeq(view.getStartSeq());
3307 ColourSchemeI cs = null;
3308 // apply colourschemes
3309 if (view.getBgColour() != null)
3311 if (view.getBgColour().startsWith("ucs"))
3313 cs = GetUserColourScheme(jms, view.getBgColour());
3315 else if (view.getBgColour().startsWith("Annotation"))
3317 // int find annotation
3318 if (af.viewport.getAlignment().getAlignmentAnnotation() != null)
3320 for (int i = 0; i < af.viewport.getAlignment()
3321 .getAlignmentAnnotation().length; i++)
3323 if (af.viewport.getAlignment().getAlignmentAnnotation()[i].label
3324 .equals(view.getAnnotationColours().getAnnotation()))
3326 if (af.viewport.getAlignment().getAlignmentAnnotation()[i]
3327 .getThreshold() == null)
3329 af.viewport.getAlignment().getAlignmentAnnotation()[i]
3330 .setThreshold(new jalview.datamodel.GraphLine(view
3331 .getAnnotationColours().getThreshold(),
3332 "Threshold", java.awt.Color.black)
3337 if (view.getAnnotationColours().getColourScheme()
3340 cs = new AnnotationColourGradient(af.viewport
3341 .getAlignment().getAlignmentAnnotation()[i],
3342 new java.awt.Color(view.getAnnotationColours()
3343 .getMinColour()), new java.awt.Color(view
3344 .getAnnotationColours().getMaxColour()),
3345 view.getAnnotationColours().getAboveThreshold());
3347 else if (view.getAnnotationColours().getColourScheme()
3350 cs = new AnnotationColourGradient(af.viewport
3351 .getAlignment().getAlignmentAnnotation()[i],
3352 GetUserColourScheme(jms, view
3353 .getAnnotationColours().getColourScheme()),
3354 view.getAnnotationColours().getAboveThreshold());
3358 cs = new AnnotationColourGradient(af.viewport
3359 .getAlignment().getAlignmentAnnotation()[i],
3360 ColourSchemeProperty.getColour(al, view
3361 .getAnnotationColours().getColourScheme()),
3362 view.getAnnotationColours().getAboveThreshold());
3364 if (view.getAnnotationColours().hasPerSequence())
3366 ((AnnotationColourGradient)cs).setSeqAssociated(view.getAnnotationColours().isPerSequence());
3368 if (view.getAnnotationColours().hasPredefinedColours())
3370 ((AnnotationColourGradient)cs).setPredefinedColours(view.getAnnotationColours().isPredefinedColours());
3372 // Also use these settings for all the groups
3373 if (al.getGroups() != null)
3375 for (int g = 0; g < al.getGroups().size(); g++)
3377 jalview.datamodel.SequenceGroup sg = al.getGroups()
3387 * (view.getAnnotationColours().getColourScheme().equals("None"
3388 * )) { sg.cs = new AnnotationColourGradient(
3389 * af.viewport.getAlignment().getAlignmentAnnotation()[i], new
3390 * java.awt.Color(view.getAnnotationColours().
3391 * getMinColour()), new
3392 * java.awt.Color(view.getAnnotationColours().
3394 * view.getAnnotationColours().getAboveThreshold()); } else
3397 sg.cs = new AnnotationColourGradient(af.viewport
3398 .getAlignment().getAlignmentAnnotation()[i],
3399 sg.cs, view.getAnnotationColours()
3400 .getAboveThreshold());
3401 if (cs instanceof AnnotationColourGradient)
3403 if (view.getAnnotationColours().hasPerSequence())
3405 ((AnnotationColourGradient)cs).setSeqAssociated(view.getAnnotationColours().isPerSequence());
3407 if (view.getAnnotationColours().hasPredefinedColours())
3409 ((AnnotationColourGradient)cs).setPredefinedColours(view.getAnnotationColours().isPredefinedColours());
3425 cs = ColourSchemeProperty.getColour(al, view.getBgColour());
3430 cs.setThreshold(view.getPidThreshold(), true);
3431 cs.setConsensus(af.viewport.getSequenceConsensusHash());
3435 af.viewport.setGlobalColourScheme(cs);
3436 af.viewport.setColourAppliesToAllGroups(false);
3438 if (view.getConservationSelected() && cs != null)
3440 cs.setConservationInc(view.getConsThreshold());
3443 af.changeColour(cs);
3445 af.viewport.setColourAppliesToAllGroups(true);
3447 if (view.getShowSequenceFeatures())
3449 af.viewport.showSequenceFeatures = true;
3451 if (view.hasCentreColumnLabels())
3453 af.viewport.setCentreColumnLabels(view.getCentreColumnLabels());
3455 if (view.hasIgnoreGapsinConsensus())
3457 af.viewport.setIgnoreGapsConsensus(view.getIgnoreGapsinConsensus(),
3460 if (view.hasFollowHighlight())
3462 af.viewport.followHighlight = view.getFollowHighlight();
3464 if (view.hasFollowSelection())
3466 af.viewport.followSelection = view.getFollowSelection();
3468 if (view.hasShowConsensusHistogram())
3470 af.viewport.setShowConsensusHistogram(view
3471 .getShowConsensusHistogram());
3475 af.viewport.setShowConsensusHistogram(true);
3477 if (view.hasShowSequenceLogo())
3479 af.viewport.setShowSequenceLogo(view.getShowSequenceLogo());
3483 af.viewport.setShowSequenceLogo(false);
3485 if (view.hasNormaliseSequenceLogo())
3487 af.viewport.setNormaliseSequenceLogo(view.getNormaliseSequenceLogo());
3489 if (view.hasShowDbRefTooltip())
3491 af.viewport.setShowDbRefs(view.getShowDbRefTooltip());
3493 if (view.hasShowNPfeatureTooltip())
3495 af.viewport.setShowNpFeats(view.hasShowNPfeatureTooltip());
3497 if (view.hasShowGroupConsensus())
3499 af.viewport.setShowGroupConsensus(view.getShowGroupConsensus());
3503 af.viewport.setShowGroupConsensus(false);
3505 if (view.hasShowGroupConservation())
3507 af.viewport.setShowGroupConservation(view.getShowGroupConservation());
3511 af.viewport.setShowGroupConservation(false);
3514 // recover featre settings
3515 if (jms.getFeatureSettings() != null)
3517 af.viewport.featuresDisplayed = new Hashtable();
3518 String[] renderOrder = new String[jms.getFeatureSettings()
3519 .getSettingCount()];
3520 for (int fs = 0; fs < jms.getFeatureSettings().getSettingCount(); fs++)
3522 Setting setting = jms.getFeatureSettings().getSetting(fs);
3523 if (setting.hasMincolour())
3525 GraduatedColor gc = setting.hasMin() ? new GraduatedColor(
3526 new java.awt.Color(setting.getMincolour()),
3527 new java.awt.Color(setting.getColour()),
3528 setting.getMin(), setting.getMax()) : new GraduatedColor(
3529 new java.awt.Color(setting.getMincolour()),
3530 new java.awt.Color(setting.getColour()), 0, 1);
3531 if (setting.hasThreshold())
3533 gc.setThresh(setting.getThreshold());
3534 gc.setThreshType(setting.getThreshstate());
3536 gc.setAutoScaled(true); // default
3537 if (setting.hasAutoScale())
3539 gc.setAutoScaled(setting.getAutoScale());
3541 if (setting.hasColourByLabel())
3543 gc.setColourByLabel(setting.getColourByLabel());
3545 // and put in the feature colour table.
3546 af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().setColour(
3547 setting.getType(), gc);
3551 af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().setColour(
3553 new java.awt.Color(setting.getColour()));
3555 renderOrder[fs] = setting.getType();
3556 if (setting.hasOrder())
3557 af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().setOrder(
3558 setting.getType(), setting.getOrder());
3560 af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().setOrder(
3562 fs / jms.getFeatureSettings().getSettingCount());
3563 if (setting.getDisplay())
3565 af.viewport.featuresDisplayed.put(setting.getType(), new Integer(
3566 setting.getColour()));
3569 af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().renderOrder = renderOrder;
3571 af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().featureGroups = fgtable = new Hashtable();
3572 for (int gs = 0; gs < jms.getFeatureSettings().getGroupCount(); gs++)
3574 Group grp = jms.getFeatureSettings().getGroup(gs);
3575 fgtable.put(grp.getName(), new Boolean(grp.getDisplay()));
3579 if (view.getHiddenColumnsCount() > 0)
3581 for (int c = 0; c < view.getHiddenColumnsCount(); c++)
3583 af.viewport.hideColumns(view.getHiddenColumns(c).getStart(), view
3584 .getHiddenColumns(c).getEnd() // +1
3588 if (view.getCalcIdParam() != null)
3590 for (CalcIdParam calcIdParam : view.getCalcIdParam())
3592 if (calcIdParam != null)
3594 if (recoverCalcIdParam(calcIdParam, af.viewport))
3599 warn("Couldn't recover parameters for "
3600 + calcIdParam.getCalcId());
3605 af.setMenusFromViewport(af.viewport);
3606 // TODO: we don't need to do this if the viewport is aready visible.
3607 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
3609 af.alignPanel.updateAnnotation(false, true); // recompute any autoannotation
3610 reorderAutoannotation(af, al, autoAlan);
3611 af.alignPanel.alignmentChanged();
3615 private void reorderAutoannotation(AlignFrame af, Alignment al,
3616 ArrayList<JvAnnotRow> autoAlan)
3618 // copy over visualization settings for autocalculated annotation in the
3620 if (al.getAlignmentAnnotation() != null)
3623 * Kludge for magic autoannotation names (see JAL-811)
3625 String[] magicNames = new String[]
3626 { "Consensus", "Quality", "Conservation" };
3627 JvAnnotRow nullAnnot = new JvAnnotRow(-1, null);
3628 Hashtable<String, JvAnnotRow> visan = new Hashtable<String, JvAnnotRow>();
3629 for (String nm : magicNames)
3631 visan.put(nm, nullAnnot);
3633 for (JvAnnotRow auan : autoAlan)
3635 visan.put(auan.template.label
3636 + (auan.template.getCalcId() == null ? "" : "\t"
3637 + auan.template.getCalcId()), auan);
3639 int hSize = al.getAlignmentAnnotation().length;
3640 ArrayList<JvAnnotRow> reorder = new ArrayList<JvAnnotRow>();
3641 // work through any autoCalculated annotation already on the view
3642 // removing it if it should be placed in a different location on the
3643 // annotation panel.
3644 List<String> remains = new ArrayList(visan.keySet());
3645 for (int h = 0; h < hSize; h++)
3647 jalview.datamodel.AlignmentAnnotation jalan = al
3648 .getAlignmentAnnotation()[h];
3649 if (jalan.autoCalculated)
3652 JvAnnotRow valan = visan.get(k = jalan.label);
3653 if (jalan.getCalcId() != null)
3655 valan = visan.get(k = jalan.label + "\t" + jalan.getCalcId());
3660 // delete the auto calculated row from the alignment
3661 al.deleteAnnotation(jalan, false);
3665 if (valan != nullAnnot)
3667 if (jalan != valan.template)
3669 // newly created autoannotation row instance
3670 // so keep a reference to the visible annotation row
3671 // and copy over all relevant attributes
3672 if (valan.template.graphHeight >= 0)
3675 jalan.graphHeight = valan.template.graphHeight;
3677 jalan.visible = valan.template.visible;
3679 reorder.add(new JvAnnotRow(valan.order, jalan));
3684 // Add any (possibly stale) autocalculated rows that were not appended to
3685 // the view during construction
3686 for (String other : remains)
3688 JvAnnotRow othera = visan.get(other);
3689 if (othera != nullAnnot && othera.template.getCalcId() != null
3690 && othera.template.getCalcId().length() > 0)
3692 reorder.add(othera);
3695 // now put the automatic annotation in its correct place
3696 int s = 0, srt[] = new int[reorder.size()];
3697 JvAnnotRow[] rws = new JvAnnotRow[reorder.size()];
3698 for (JvAnnotRow jvar : reorder)
3701 srt[s++] = jvar.order;
3704 jalview.util.QuickSort.sort(srt, rws);
3705 // and re-insert the annotation at its correct position
3706 for (JvAnnotRow jvar : rws)
3708 al.addAnnotation(jvar.template, jvar.order);
3710 af.alignPanel.adjustAnnotationHeight();
3714 Hashtable skipList = null;
3717 * TODO remove this method
3720 * @return AlignFrame bound to sequenceSetId from view, if one exists. private
3721 * AlignFrame getSkippedFrame(Viewport view) { if (skipList==null) {
3722 * throw new Error("Implementation Error. No skipList defined for this
3723 * Jalview2XML instance."); } return (AlignFrame)
3724 * skipList.get(view.getSequenceSetId()); }
3728 * Check if the Jalview view contained in object should be skipped or not.
3731 * @return true if view's sequenceSetId is a key in skipList
3733 private boolean skipViewport(JalviewModel object)
3735 if (skipList == null)
3740 if (skipList.containsKey(id = object.getJalviewModelSequence()
3741 .getViewport()[0].getSequenceSetId()))
3743 if (Cache.log != null && Cache.log.isDebugEnabled())
3745 Cache.log.debug("Skipping seuqence set id " + id);
3752 public void AddToSkipList(AlignFrame af)
3754 if (skipList == null)
3756 skipList = new Hashtable();
3758 skipList.put(af.getViewport().getSequenceSetId(), af);
3761 public void clearSkipList()
3763 if (skipList != null)
3770 private void recoverDatasetFor(SequenceSet vamsasSet, Alignment al)
3772 jalview.datamodel.Alignment ds = getDatasetFor(vamsasSet.getDatasetId());
3773 Vector dseqs = null;
3776 // create a list of new dataset sequences
3777 dseqs = new Vector();
3779 for (int i = 0, iSize = vamsasSet.getSequenceCount(); i < iSize; i++)
3781 Sequence vamsasSeq = vamsasSet.getSequence(i);
3782 ensureJalviewDatasetSequence(vamsasSeq, ds, dseqs);
3784 // create a new dataset
3787 SequenceI[] dsseqs = new SequenceI[dseqs.size()];
3788 dseqs.copyInto(dsseqs);
3789 ds = new jalview.datamodel.Alignment(dsseqs);
3790 debug("Created new dataset " + vamsasSet.getDatasetId()
3791 + " for alignment " + System.identityHashCode(al));
3792 addDatasetRef(vamsasSet.getDatasetId(), ds);
3794 // set the dataset for the newly imported alignment.
3795 if (al.getDataset() == null)
3804 * sequence definition to create/merge dataset sequence for
3808 * vector to add new dataset sequence to
3810 private void ensureJalviewDatasetSequence(Sequence vamsasSeq,
3811 AlignmentI ds, Vector dseqs)
3813 // JBP TODO: Check this is called for AlCodonFrames to support recovery of
3815 jalview.datamodel.Sequence sq = (jalview.datamodel.Sequence) seqRefIds
3816 .get(vamsasSeq.getId());
3817 jalview.datamodel.SequenceI dsq = null;
3818 if (sq != null && sq.getDatasetSequence() != null)
3820 dsq = sq.getDatasetSequence();
3823 String sqid = vamsasSeq.getDsseqid();
3826 // need to create or add a new dataset sequence reference to this sequence
3829 dsq = (jalview.datamodel.SequenceI) seqRefIds.get(sqid);
3834 // make a new dataset sequence
3835 dsq = sq.createDatasetSequence();
3838 // make up a new dataset reference for this sequence
3839 sqid = seqHash(dsq);
3841 dsq.setVamsasId(uniqueSetSuffix + sqid);
3842 seqRefIds.put(sqid, dsq);
3847 dseqs.addElement(dsq);
3852 ds.addSequence(dsq);
3858 { // make this dataset sequence sq's dataset sequence
3859 sq.setDatasetSequence(dsq);
3860 // and update the current dataset alignment
3865 if (!dseqs.contains(dsq))
3872 if (ds.findIndex(dsq) < 0)
3874 ds.addSequence(dsq);
3881 // TODO: refactor this as a merge dataset sequence function
3882 // now check that sq (the dataset sequence) sequence really is the union of
3883 // all references to it
3884 // boolean pre = sq.getStart() < dsq.getStart();
3885 // boolean post = sq.getEnd() > dsq.getEnd();
3889 StringBuffer sb = new StringBuffer();
3890 String newres = jalview.analysis.AlignSeq.extractGaps(
3891 jalview.util.Comparison.GapChars, sq.getSequenceAsString());
3892 if (!newres.equalsIgnoreCase(dsq.getSequenceAsString())
3893 && newres.length() > dsq.getLength())
3895 // Update with the longer sequence.
3899 * if (pre) { sb.insert(0, newres .substring(0, dsq.getStart() -
3900 * sq.getStart())); dsq.setStart(sq.getStart()); } if (post) {
3901 * sb.append(newres.substring(newres.length() - sq.getEnd() -
3902 * dsq.getEnd())); dsq.setEnd(sq.getEnd()); }
3904 dsq.setSequence(newres);
3906 // TODO: merges will never happen if we 'know' we have the real dataset
3907 // sequence - this should be detected when id==dssid
3909 .println("DEBUG Notice: Merged dataset sequence (if you see this often, post at http://issues.jalview.org/browse/JAL-1474)"); // ("
3910 // + (pre ? "prepended" : "") + " "
3911 // + (post ? "appended" : ""));
3916 java.util.Hashtable datasetIds = null;
3918 java.util.IdentityHashMap dataset2Ids = null;
3920 private Alignment getDatasetFor(String datasetId)
3922 if (datasetIds == null)
3924 datasetIds = new Hashtable();
3927 if (datasetIds.containsKey(datasetId))
3929 return (Alignment) datasetIds.get(datasetId);
3934 private void addDatasetRef(String datasetId, Alignment dataset)
3936 if (datasetIds == null)
3938 datasetIds = new Hashtable();
3940 datasetIds.put(datasetId, dataset);
3944 * make a new dataset ID for this jalview dataset alignment
3949 private String getDatasetIdRef(jalview.datamodel.Alignment dataset)
3951 if (dataset.getDataset() != null)
3953 warn("Serious issue! Dataset Object passed to getDatasetIdRef is not a Jalview DATASET alignment...");
3955 String datasetId = makeHashCode(dataset, null);
3956 if (datasetId == null)
3958 // make a new datasetId and record it
3959 if (dataset2Ids == null)
3961 dataset2Ids = new IdentityHashMap();
3965 datasetId = (String) dataset2Ids.get(dataset);
3967 if (datasetId == null)
3969 datasetId = "ds" + dataset2Ids.size() + 1;
3970 dataset2Ids.put(dataset, datasetId);
3976 private void addDBRefs(SequenceI datasetSequence, Sequence sequence)
3978 for (int d = 0; d < sequence.getDBRefCount(); d++)
3980 DBRef dr = sequence.getDBRef(d);
3981 jalview.datamodel.DBRefEntry entry = new jalview.datamodel.DBRefEntry(
3982 sequence.getDBRef(d).getSource(), sequence.getDBRef(d)
3983 .getVersion(), sequence.getDBRef(d).getAccessionId());
3984 if (dr.getMapping() != null)
3986 entry.setMap(addMapping(dr.getMapping()));
3988 datasetSequence.addDBRef(entry);
3992 private jalview.datamodel.Mapping addMapping(Mapping m)
3994 SequenceI dsto = null;
3995 // Mapping m = dr.getMapping();
3996 int fr[] = new int[m.getMapListFromCount() * 2];
3997 Enumeration f = m.enumerateMapListFrom();
3998 for (int _i = 0; f.hasMoreElements(); _i += 2)
4000 MapListFrom mf = (MapListFrom) f.nextElement();
4001 fr[_i] = mf.getStart();
4002 fr[_i + 1] = mf.getEnd();
4004 int fto[] = new int[m.getMapListToCount() * 2];
4005 f = m.enumerateMapListTo();
4006 for (int _i = 0; f.hasMoreElements(); _i += 2)
4008 MapListTo mf = (MapListTo) f.nextElement();
4009 fto[_i] = mf.getStart();
4010 fto[_i + 1] = mf.getEnd();
4012 jalview.datamodel.Mapping jmap = new jalview.datamodel.Mapping(dsto,
4013 fr, fto, (int) m.getMapFromUnit(), (int) m.getMapToUnit());
4014 if (m.getMappingChoice() != null)
4016 MappingChoice mc = m.getMappingChoice();
4017 if (mc.getDseqFor() != null)
4019 String dsfor = "" + mc.getDseqFor();
4020 if (seqRefIds.containsKey(dsfor))
4025 jmap.setTo((SequenceI) seqRefIds.get(dsfor));
4029 frefedSequence.add(new Object[]
4036 * local sequence definition
4038 Sequence ms = mc.getSequence();
4039 jalview.datamodel.Sequence djs = null;
4040 String sqid = ms.getDsseqid();
4041 if (sqid != null && sqid.length() > 0)
4044 * recover dataset sequence
4046 djs = (jalview.datamodel.Sequence) seqRefIds.get(sqid);
4051 .println("Warning - making up dataset sequence id for DbRef sequence map reference");
4052 sqid = ((Object) ms).toString(); // make up a new hascode for
4053 // undefined dataset sequence hash
4054 // (unlikely to happen)
4060 * make a new dataset sequence and add it to refIds hash
4062 djs = new jalview.datamodel.Sequence(ms.getName(),
4064 djs.setStart(jmap.getMap().getToLowest());
4065 djs.setEnd(jmap.getMap().getToHighest());
4066 djs.setVamsasId(uniqueSetSuffix + sqid);
4068 seqRefIds.put(sqid, djs);
4071 jalview.bin.Cache.log.debug("about to recurse on addDBRefs.");
4080 public jalview.gui.AlignmentPanel copyAlignPanel(AlignmentPanel ap,
4081 boolean keepSeqRefs)
4084 jalview.schemabinding.version2.JalviewModel jm = SaveState(ap, null,
4090 jm.getJalviewModelSequence().getViewport(0).setSequenceSetId(null);
4094 uniqueSetSuffix = "";
4095 jm.getJalviewModelSequence().getViewport(0).setId(null); // we don't
4100 if (this.frefedSequence == null)
4102 frefedSequence = new Vector();
4105 viewportsAdded = new Hashtable();
4107 AlignFrame af = LoadFromObject(jm, null, false, null);
4108 af.alignPanels.clear();
4109 af.closeMenuItem_actionPerformed(true);
4112 * if(ap.av.getAlignment().getAlignmentAnnotation()!=null) { for(int i=0;
4113 * i<ap.av.getAlignment().getAlignmentAnnotation().length; i++) {
4114 * if(!ap.av.getAlignment().getAlignmentAnnotation()[i].autoCalculated) {
4115 * af.alignPanel.av.getAlignment().getAlignmentAnnotation()[i] =
4116 * ap.av.getAlignment().getAlignmentAnnotation()[i]; } } }
4119 return af.alignPanel;
4123 * flag indicating if hashtables should be cleared on finalization TODO this
4124 * flag may not be necessary
4126 private final boolean _cleartables = true;
4128 private Hashtable jvids2vobj;
4133 * @see java.lang.Object#finalize()
4136 protected void finalize() throws Throwable
4138 // really make sure we have no buried refs left.
4143 this.seqRefIds = null;
4144 this.seqsToIds = null;
4148 private void warn(String msg)
4153 private void warn(String msg, Exception e)
4155 if (Cache.log != null)
4159 Cache.log.warn(msg, e);
4163 Cache.log.warn(msg);
4168 System.err.println("Warning: " + msg);
4171 e.printStackTrace();
4176 private void debug(String string)
4178 debug(string, null);
4181 private void debug(String msg, Exception e)
4183 if (Cache.log != null)
4187 Cache.log.debug(msg, e);
4191 Cache.log.debug(msg);
4196 System.err.println("Warning: " + msg);
4199 e.printStackTrace();
4205 * set the object to ID mapping tables used to write/recover objects and XML
4206 * ID strings for the jalview project. If external tables are provided then
4207 * finalize and clearSeqRefs will not clear the tables when the Jalview2XML
4208 * object goes out of scope. - also populates the datasetIds hashtable with
4209 * alignment objects containing dataset sequences
4212 * Map from ID strings to jalview datamodel
4214 * Map from jalview datamodel to ID strings
4218 public void setObjectMappingTables(Hashtable vobj2jv,
4219 IdentityHashMap jv2vobj)
4221 this.jv2vobj = jv2vobj;
4222 this.vobj2jv = vobj2jv;
4223 Iterator ds = jv2vobj.keySet().iterator();
4225 while (ds.hasNext())
4227 Object jvobj = ds.next();
4228 id = jv2vobj.get(jvobj).toString();
4229 if (jvobj instanceof jalview.datamodel.Alignment)
4231 if (((jalview.datamodel.Alignment) jvobj).getDataset() == null)
4233 addDatasetRef(id, (jalview.datamodel.Alignment) jvobj);
4236 else if (jvobj instanceof jalview.datamodel.Sequence)
4238 // register sequence object so the XML parser can recover it.
4239 if (seqRefIds == null)
4241 seqRefIds = new Hashtable();
4243 if (seqsToIds == null)
4245 seqsToIds = new IdentityHashMap();
4247 seqRefIds.put(jv2vobj.get(jvobj).toString(), jvobj);
4248 seqsToIds.put(jvobj, id);
4250 else if (jvobj instanceof jalview.datamodel.AlignmentAnnotation)
4252 if (annotationIds == null)
4254 annotationIds = new Hashtable();
4257 annotationIds.put(anid = jv2vobj.get(jvobj).toString(), jvobj);
4258 jalview.datamodel.AlignmentAnnotation jvann = (jalview.datamodel.AlignmentAnnotation) jvobj;
4259 if (jvann.annotationId == null)
4261 jvann.annotationId = anid;
4263 if (!jvann.annotationId.equals(anid))
4265 // TODO verify that this is the correct behaviour
4266 this.warn("Overriding Annotation ID for " + anid
4267 + " from different id : " + jvann.annotationId);
4268 jvann.annotationId = anid;
4271 else if (jvobj instanceof String)
4273 if (jvids2vobj == null)
4275 jvids2vobj = new Hashtable();
4276 jvids2vobj.put(jvobj, jv2vobj.get(jvobj).toString());
4280 Cache.log.debug("Ignoring " + jvobj.getClass() + " (ID = " + id);
4285 * set the uniqueSetSuffix used to prefix/suffix object IDs for jalview
4286 * objects created from the project archive. If string is null (default for
4287 * construction) then suffix will be set automatically.
4291 public void setUniqueSetSuffix(String string)
4293 uniqueSetSuffix = string;
4298 * uses skipList2 as the skipList for skipping views on sequence sets
4299 * associated with keys in the skipList
4303 public void setSkipList(Hashtable skipList2)
4305 skipList = skipList2;