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.
3184 * @param supported - minimum version we are comparing against
3185 * @param version - version of data being processsed.
3186 * @return true if version is development/null or evaluates to the same or
3187 * later X.Y.Z (where X,Y,Z are like [0-9]+b?[0-9]*)
3189 private boolean isVersionStringLaterThan(String supported, String version)
3191 if (version == null || version.equalsIgnoreCase("DEVELOPMENT BUILD")
3192 || version.equalsIgnoreCase("Test"))
3194 System.err.println("Assuming project file with "
3195 + (version == null ? "null" : version)
3196 + " is compatible with Jalview version " + supported);
3201 StringTokenizer currentV = new StringTokenizer(supported, "."), fileV = new StringTokenizer(
3203 while (currentV.hasMoreTokens() && fileV.hasMoreTokens())
3205 // convert b to decimal to catch bugfix releases within a series
3206 String curT = currentV.nextToken().toLowerCase().replace('b', '.');
3207 String fileT = fileV.nextToken().toLowerCase().replace('b', '.');
3210 if (Float.valueOf(curT) > Float.valueOf(fileT))
3212 // current version is newer than the version that wrote the file
3215 } catch (NumberFormatException nfe)
3218 .println("** WARNING: Version comparison failed for tokens ("
3222 + ")\n** Current: '"
3223 + supported + "' and Version: '" + version + "'");
3226 if (currentV.hasMoreElements())
3228 // fileV has no minor version but identical series to current
3235 Vector<AppJmol> newStructureViewers = null;
3237 protected void addNewStructureViewer(AppJmol sview)
3239 if (newStructureViewers != null)
3241 sview.jmb.setFinishedLoadingFromArchive(false);
3242 newStructureViewers.add(sview);
3246 protected void setLoadingFinishedForNewStructureViewers()
3248 if (newStructureViewers != null)
3250 for (AppJmol sview : newStructureViewers)
3252 sview.jmb.setFinishedLoadingFromArchive(true);
3254 newStructureViewers.clear();
3255 newStructureViewers = null;
3259 AlignFrame loadViewport(String file, JSeq[] JSEQ, Vector hiddenSeqs,
3260 Alignment al, JalviewModelSequence jms, Viewport view,
3261 String uniqueSeqSetId, String viewId,
3262 ArrayList<JvAnnotRow> autoAlan)
3264 AlignFrame af = null;
3265 af = new AlignFrame(al, view.getWidth(), view.getHeight(),
3266 uniqueSeqSetId, viewId);
3268 af.setFileName(file, "Jalview");
3270 for (int i = 0; i < JSEQ.length; i++)
3272 af.viewport.setSequenceColour(af.viewport.getAlignment()
3273 .getSequenceAt(i), new java.awt.Color(JSEQ[i].getColour()));
3276 af.viewport.gatherViewsHere = view.getGatheredViews();
3278 if (view.getSequenceSetId() != null)
3280 jalview.gui.AlignViewport av = (jalview.gui.AlignViewport) viewportsAdded
3281 .get(uniqueSeqSetId);
3283 af.viewport.setSequenceSetId(uniqueSeqSetId);
3286 // propagate shared settings to this new view
3287 af.viewport.historyList = av.historyList;
3288 af.viewport.redoList = av.redoList;
3292 viewportsAdded.put(uniqueSeqSetId, af.viewport);
3294 // TODO: check if this method can be called repeatedly without
3295 // side-effects if alignpanel already registered.
3296 PaintRefresher.Register(af.alignPanel, uniqueSeqSetId);
3298 // apply Hidden regions to view.
3299 if (hiddenSeqs != null)
3301 for (int s = 0; s < JSEQ.length; s++)
3303 jalview.datamodel.SequenceGroup hidden = new jalview.datamodel.SequenceGroup();
3305 for (int r = 0; r < JSEQ[s].getHiddenSequencesCount(); r++)
3308 al.getSequenceAt(JSEQ[s].getHiddenSequences(r)), false);
3310 af.viewport.hideRepSequences(al.getSequenceAt(s), hidden);
3313 jalview.datamodel.SequenceI[] hseqs = new jalview.datamodel.SequenceI[hiddenSeqs
3316 for (int s = 0; s < hiddenSeqs.size(); s++)
3318 hseqs[s] = (jalview.datamodel.SequenceI) hiddenSeqs.elementAt(s);
3321 af.viewport.hideSequence(hseqs);
3324 // recover view properties and display parameters
3325 if (view.getViewName() != null)
3327 af.viewport.viewName = view.getViewName();
3328 af.setInitialTabVisible();
3330 af.setBounds(view.getXpos(), view.getYpos(), view.getWidth(),
3333 af.viewport.setShowAnnotation(view.getShowAnnotation());
3334 af.viewport.setAbovePIDThreshold(view.getPidSelected());
3336 af.viewport.setColourText(view.getShowColourText());
3338 af.viewport.setConservationSelected(view.getConservationSelected());
3339 af.viewport.setShowJVSuffix(view.getShowFullId());
3340 af.viewport.rightAlignIds = view.getRightAlignIds();
3341 af.viewport.setFont(new java.awt.Font(view.getFontName(), view
3342 .getFontStyle(), view.getFontSize()));
3343 af.alignPanel.fontChanged();
3344 af.viewport.setRenderGaps(view.getRenderGaps());
3345 af.viewport.setWrapAlignment(view.getWrapAlignment());
3346 af.alignPanel.setWrapAlignment(view.getWrapAlignment());
3347 af.viewport.setShowAnnotation(view.getShowAnnotation());
3348 af.alignPanel.setAnnotationVisible(view.getShowAnnotation());
3350 af.viewport.setShowBoxes(view.getShowBoxes());
3352 af.viewport.setShowText(view.getShowText());
3354 af.viewport.textColour = new java.awt.Color(view.getTextCol1());
3355 af.viewport.textColour2 = new java.awt.Color(view.getTextCol2());
3356 af.viewport.thresholdTextColour = view.getTextColThreshold();
3357 af.viewport.setShowUnconserved(view.hasShowUnconserved() ? view
3358 .isShowUnconserved() : false);
3359 af.viewport.setStartRes(view.getStartRes());
3360 af.viewport.setStartSeq(view.getStartSeq());
3362 ColourSchemeI cs = null;
3363 // apply colourschemes
3364 if (view.getBgColour() != null)
3366 if (view.getBgColour().startsWith("ucs"))
3368 cs = GetUserColourScheme(jms, view.getBgColour());
3370 else if (view.getBgColour().startsWith("Annotation"))
3372 // int find annotation
3373 if (af.viewport.getAlignment().getAlignmentAnnotation() != null)
3375 for (int i = 0; i < af.viewport.getAlignment()
3376 .getAlignmentAnnotation().length; i++)
3378 if (af.viewport.getAlignment().getAlignmentAnnotation()[i].label
3379 .equals(view.getAnnotationColours().getAnnotation()))
3381 if (af.viewport.getAlignment().getAlignmentAnnotation()[i]
3382 .getThreshold() == null)
3384 af.viewport.getAlignment().getAlignmentAnnotation()[i]
3385 .setThreshold(new jalview.datamodel.GraphLine(view
3386 .getAnnotationColours().getThreshold(),
3387 "Threshold", java.awt.Color.black)
3392 if (view.getAnnotationColours().getColourScheme()
3395 cs = new AnnotationColourGradient(af.viewport
3396 .getAlignment().getAlignmentAnnotation()[i],
3397 new java.awt.Color(view.getAnnotationColours()
3398 .getMinColour()), new java.awt.Color(view
3399 .getAnnotationColours().getMaxColour()),
3400 view.getAnnotationColours().getAboveThreshold());
3402 else if (view.getAnnotationColours().getColourScheme()
3405 cs = new AnnotationColourGradient(af.viewport
3406 .getAlignment().getAlignmentAnnotation()[i],
3407 GetUserColourScheme(jms, view
3408 .getAnnotationColours().getColourScheme()),
3409 view.getAnnotationColours().getAboveThreshold());
3413 cs = new AnnotationColourGradient(af.viewport
3414 .getAlignment().getAlignmentAnnotation()[i],
3415 ColourSchemeProperty.getColour(al, view
3416 .getAnnotationColours().getColourScheme()),
3417 view.getAnnotationColours().getAboveThreshold());
3419 if (view.getAnnotationColours().hasPerSequence())
3421 ((AnnotationColourGradient)cs).setSeqAssociated(view.getAnnotationColours().isPerSequence());
3423 if (view.getAnnotationColours().hasPredefinedColours())
3425 ((AnnotationColourGradient)cs).setPredefinedColours(view.getAnnotationColours().isPredefinedColours());
3427 // Also use these settings for all the groups
3428 if (al.getGroups() != null)
3430 for (int g = 0; g < al.getGroups().size(); g++)
3432 jalview.datamodel.SequenceGroup sg = al.getGroups()
3442 * (view.getAnnotationColours().getColourScheme().equals("None"
3443 * )) { sg.cs = new AnnotationColourGradient(
3444 * af.viewport.getAlignment().getAlignmentAnnotation()[i], new
3445 * java.awt.Color(view.getAnnotationColours().
3446 * getMinColour()), new
3447 * java.awt.Color(view.getAnnotationColours().
3449 * view.getAnnotationColours().getAboveThreshold()); } else
3452 sg.cs = new AnnotationColourGradient(af.viewport
3453 .getAlignment().getAlignmentAnnotation()[i],
3454 sg.cs, view.getAnnotationColours()
3455 .getAboveThreshold());
3456 if (cs instanceof AnnotationColourGradient)
3458 if (view.getAnnotationColours().hasPerSequence())
3460 ((AnnotationColourGradient)cs).setSeqAssociated(view.getAnnotationColours().isPerSequence());
3462 if (view.getAnnotationColours().hasPredefinedColours())
3464 ((AnnotationColourGradient)cs).setPredefinedColours(view.getAnnotationColours().isPredefinedColours());
3480 cs = ColourSchemeProperty.getColour(al, view.getBgColour());
3485 cs.setThreshold(view.getPidThreshold(), true);
3486 cs.setConsensus(af.viewport.getSequenceConsensusHash());
3490 af.viewport.setGlobalColourScheme(cs);
3491 af.viewport.setColourAppliesToAllGroups(false);
3493 if (view.getConservationSelected() && cs != null)
3495 cs.setConservationInc(view.getConsThreshold());
3498 af.changeColour(cs);
3500 af.viewport.setColourAppliesToAllGroups(true);
3502 if (view.getShowSequenceFeatures())
3504 af.viewport.showSequenceFeatures = true;
3506 if (view.hasCentreColumnLabels())
3508 af.viewport.setCentreColumnLabels(view.getCentreColumnLabels());
3510 if (view.hasIgnoreGapsinConsensus())
3512 af.viewport.setIgnoreGapsConsensus(view.getIgnoreGapsinConsensus(),
3515 if (view.hasFollowHighlight())
3517 af.viewport.followHighlight = view.getFollowHighlight();
3519 if (view.hasFollowSelection())
3521 af.viewport.followSelection = view.getFollowSelection();
3523 if (view.hasShowConsensusHistogram())
3525 af.viewport.setShowConsensusHistogram(view
3526 .getShowConsensusHistogram());
3530 af.viewport.setShowConsensusHistogram(true);
3532 if (view.hasShowSequenceLogo())
3534 af.viewport.setShowSequenceLogo(view.getShowSequenceLogo());
3538 af.viewport.setShowSequenceLogo(false);
3540 if (view.hasNormaliseSequenceLogo())
3542 af.viewport.setNormaliseSequenceLogo(view.getNormaliseSequenceLogo());
3544 if (view.hasShowDbRefTooltip())
3546 af.viewport.setShowDbRefs(view.getShowDbRefTooltip());
3548 if (view.hasShowNPfeatureTooltip())
3550 af.viewport.setShowNpFeats(view.hasShowNPfeatureTooltip());
3552 if (view.hasShowGroupConsensus())
3554 af.viewport.setShowGroupConsensus(view.getShowGroupConsensus());
3558 af.viewport.setShowGroupConsensus(false);
3560 if (view.hasShowGroupConservation())
3562 af.viewport.setShowGroupConservation(view.getShowGroupConservation());
3566 af.viewport.setShowGroupConservation(false);
3569 // recover featre settings
3570 if (jms.getFeatureSettings() != null)
3572 af.viewport.featuresDisplayed = new Hashtable();
3573 String[] renderOrder = new String[jms.getFeatureSettings()
3574 .getSettingCount()];
3575 for (int fs = 0; fs < jms.getFeatureSettings().getSettingCount(); fs++)
3577 Setting setting = jms.getFeatureSettings().getSetting(fs);
3578 if (setting.hasMincolour())
3580 GraduatedColor gc = setting.hasMin() ? new GraduatedColor(
3581 new java.awt.Color(setting.getMincolour()),
3582 new java.awt.Color(setting.getColour()),
3583 setting.getMin(), setting.getMax()) : new GraduatedColor(
3584 new java.awt.Color(setting.getMincolour()),
3585 new java.awt.Color(setting.getColour()), 0, 1);
3586 if (setting.hasThreshold())
3588 gc.setThresh(setting.getThreshold());
3589 gc.setThreshType(setting.getThreshstate());
3591 gc.setAutoScaled(true); // default
3592 if (setting.hasAutoScale())
3594 gc.setAutoScaled(setting.getAutoScale());
3596 if (setting.hasColourByLabel())
3598 gc.setColourByLabel(setting.getColourByLabel());
3600 // and put in the feature colour table.
3601 af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().setColour(
3602 setting.getType(), gc);
3606 af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().setColour(
3608 new java.awt.Color(setting.getColour()));
3610 renderOrder[fs] = setting.getType();
3611 if (setting.hasOrder())
3612 af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().setOrder(
3613 setting.getType(), setting.getOrder());
3615 af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().setOrder(
3617 fs / jms.getFeatureSettings().getSettingCount());
3618 if (setting.getDisplay())
3620 af.viewport.featuresDisplayed.put(setting.getType(), new Integer(
3621 setting.getColour()));
3624 af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().renderOrder = renderOrder;
3626 af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().featureGroups = fgtable = new Hashtable();
3627 for (int gs = 0; gs < jms.getFeatureSettings().getGroupCount(); gs++)
3629 Group grp = jms.getFeatureSettings().getGroup(gs);
3630 fgtable.put(grp.getName(), new Boolean(grp.getDisplay()));
3634 if (view.getHiddenColumnsCount() > 0)
3636 for (int c = 0; c < view.getHiddenColumnsCount(); c++)
3638 af.viewport.hideColumns(view.getHiddenColumns(c).getStart(), view
3639 .getHiddenColumns(c).getEnd() // +1
3643 if (view.getCalcIdParam() != null)
3645 for (CalcIdParam calcIdParam : view.getCalcIdParam())
3647 if (calcIdParam != null)
3649 if (recoverCalcIdParam(calcIdParam, af.viewport))
3654 warn("Couldn't recover parameters for "
3655 + calcIdParam.getCalcId());
3660 af.setMenusFromViewport(af.viewport);
3661 // TODO: we don't need to do this if the viewport is aready visible.
3662 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
3664 af.alignPanel.updateAnnotation(false, true); // recompute any autoannotation
3665 reorderAutoannotation(af, al, autoAlan);
3666 af.alignPanel.alignmentChanged();
3670 private void reorderAutoannotation(AlignFrame af, Alignment al,
3671 ArrayList<JvAnnotRow> autoAlan)
3673 // copy over visualization settings for autocalculated annotation in the
3675 if (al.getAlignmentAnnotation() != null)
3678 * Kludge for magic autoannotation names (see JAL-811)
3680 String[] magicNames = new String[]
3681 { "Consensus", "Quality", "Conservation" };
3682 JvAnnotRow nullAnnot = new JvAnnotRow(-1, null);
3683 Hashtable<String, JvAnnotRow> visan = new Hashtable<String, JvAnnotRow>();
3684 for (String nm : magicNames)
3686 visan.put(nm, nullAnnot);
3688 for (JvAnnotRow auan : autoAlan)
3690 visan.put(auan.template.label
3691 + (auan.template.getCalcId() == null ? "" : "\t"
3692 + auan.template.getCalcId()), auan);
3694 int hSize = al.getAlignmentAnnotation().length;
3695 ArrayList<JvAnnotRow> reorder = new ArrayList<JvAnnotRow>();
3696 // work through any autoCalculated annotation already on the view
3697 // removing it if it should be placed in a different location on the
3698 // annotation panel.
3699 List<String> remains = new ArrayList(visan.keySet());
3700 for (int h = 0; h < hSize; h++)
3702 jalview.datamodel.AlignmentAnnotation jalan = al
3703 .getAlignmentAnnotation()[h];
3704 if (jalan.autoCalculated)
3707 JvAnnotRow valan = visan.get(k = jalan.label);
3708 if (jalan.getCalcId() != null)
3710 valan = visan.get(k = jalan.label + "\t" + jalan.getCalcId());
3715 // delete the auto calculated row from the alignment
3716 al.deleteAnnotation(jalan, false);
3720 if (valan != nullAnnot)
3722 if (jalan != valan.template)
3724 // newly created autoannotation row instance
3725 // so keep a reference to the visible annotation row
3726 // and copy over all relevant attributes
3727 if (valan.template.graphHeight >= 0)
3730 jalan.graphHeight = valan.template.graphHeight;
3732 jalan.visible = valan.template.visible;
3734 reorder.add(new JvAnnotRow(valan.order, jalan));
3739 // Add any (possibly stale) autocalculated rows that were not appended to
3740 // the view during construction
3741 for (String other : remains)
3743 JvAnnotRow othera = visan.get(other);
3744 if (othera != nullAnnot && othera.template.getCalcId() != null
3745 && othera.template.getCalcId().length() > 0)
3747 reorder.add(othera);
3750 // now put the automatic annotation in its correct place
3751 int s = 0, srt[] = new int[reorder.size()];
3752 JvAnnotRow[] rws = new JvAnnotRow[reorder.size()];
3753 for (JvAnnotRow jvar : reorder)
3756 srt[s++] = jvar.order;
3759 jalview.util.QuickSort.sort(srt, rws);
3760 // and re-insert the annotation at its correct position
3761 for (JvAnnotRow jvar : rws)
3763 al.addAnnotation(jvar.template, jvar.order);
3765 af.alignPanel.adjustAnnotationHeight();
3769 Hashtable skipList = null;
3772 * TODO remove this method
3775 * @return AlignFrame bound to sequenceSetId from view, if one exists. private
3776 * AlignFrame getSkippedFrame(Viewport view) { if (skipList==null) {
3777 * throw new Error("Implementation Error. No skipList defined for this
3778 * Jalview2XML instance."); } return (AlignFrame)
3779 * skipList.get(view.getSequenceSetId()); }
3783 * Check if the Jalview view contained in object should be skipped or not.
3786 * @return true if view's sequenceSetId is a key in skipList
3788 private boolean skipViewport(JalviewModel object)
3790 if (skipList == null)
3795 if (skipList.containsKey(id = object.getJalviewModelSequence()
3796 .getViewport()[0].getSequenceSetId()))
3798 if (Cache.log != null && Cache.log.isDebugEnabled())
3800 Cache.log.debug("Skipping seuqence set id " + id);
3807 public void AddToSkipList(AlignFrame af)
3809 if (skipList == null)
3811 skipList = new Hashtable();
3813 skipList.put(af.getViewport().getSequenceSetId(), af);
3816 public void clearSkipList()
3818 if (skipList != null)
3825 private void recoverDatasetFor(SequenceSet vamsasSet, Alignment al)
3827 jalview.datamodel.Alignment ds = getDatasetFor(vamsasSet.getDatasetId());
3828 Vector dseqs = null;
3831 // create a list of new dataset sequences
3832 dseqs = new Vector();
3834 for (int i = 0, iSize = vamsasSet.getSequenceCount(); i < iSize; i++)
3836 Sequence vamsasSeq = vamsasSet.getSequence(i);
3837 ensureJalviewDatasetSequence(vamsasSeq, ds, dseqs);
3839 // create a new dataset
3842 SequenceI[] dsseqs = new SequenceI[dseqs.size()];
3843 dseqs.copyInto(dsseqs);
3844 ds = new jalview.datamodel.Alignment(dsseqs);
3845 debug("Created new dataset " + vamsasSet.getDatasetId()
3846 + " for alignment " + System.identityHashCode(al));
3847 addDatasetRef(vamsasSet.getDatasetId(), ds);
3849 // set the dataset for the newly imported alignment.
3850 if (al.getDataset() == null)
3859 * sequence definition to create/merge dataset sequence for
3863 * vector to add new dataset sequence to
3865 private void ensureJalviewDatasetSequence(Sequence vamsasSeq,
3866 AlignmentI ds, Vector dseqs)
3868 // JBP TODO: Check this is called for AlCodonFrames to support recovery of
3870 jalview.datamodel.Sequence sq = (jalview.datamodel.Sequence) seqRefIds
3871 .get(vamsasSeq.getId());
3872 jalview.datamodel.SequenceI dsq = null;
3873 if (sq != null && sq.getDatasetSequence() != null)
3875 dsq = sq.getDatasetSequence();
3878 String sqid = vamsasSeq.getDsseqid();
3881 // need to create or add a new dataset sequence reference to this sequence
3884 dsq = (jalview.datamodel.SequenceI) seqRefIds.get(sqid);
3889 // make a new dataset sequence
3890 dsq = sq.createDatasetSequence();
3893 // make up a new dataset reference for this sequence
3894 sqid = seqHash(dsq);
3896 dsq.setVamsasId(uniqueSetSuffix + sqid);
3897 seqRefIds.put(sqid, dsq);
3902 dseqs.addElement(dsq);
3907 ds.addSequence(dsq);
3913 { // make this dataset sequence sq's dataset sequence
3914 sq.setDatasetSequence(dsq);
3915 // and update the current dataset alignment
3920 if (!dseqs.contains(dsq))
3927 if (ds.findIndex(dsq) < 0)
3929 ds.addSequence(dsq);
3936 // TODO: refactor this as a merge dataset sequence function
3937 // now check that sq (the dataset sequence) sequence really is the union of
3938 // all references to it
3939 // boolean pre = sq.getStart() < dsq.getStart();
3940 // boolean post = sq.getEnd() > dsq.getEnd();
3944 StringBuffer sb = new StringBuffer();
3945 String newres = jalview.analysis.AlignSeq.extractGaps(
3946 jalview.util.Comparison.GapChars, sq.getSequenceAsString());
3947 if (!newres.equalsIgnoreCase(dsq.getSequenceAsString())
3948 && newres.length() > dsq.getLength())
3950 // Update with the longer sequence.
3954 * if (pre) { sb.insert(0, newres .substring(0, dsq.getStart() -
3955 * sq.getStart())); dsq.setStart(sq.getStart()); } if (post) {
3956 * sb.append(newres.substring(newres.length() - sq.getEnd() -
3957 * dsq.getEnd())); dsq.setEnd(sq.getEnd()); }
3959 dsq.setSequence(newres);
3961 // TODO: merges will never happen if we 'know' we have the real dataset
3962 // sequence - this should be detected when id==dssid
3964 .println("DEBUG Notice: Merged dataset sequence (if you see this often, post at http://issues.jalview.org/browse/JAL-1474)"); // ("
3965 // + (pre ? "prepended" : "") + " "
3966 // + (post ? "appended" : ""));
3971 java.util.Hashtable datasetIds = null;
3973 java.util.IdentityHashMap dataset2Ids = null;
3975 private Alignment getDatasetFor(String datasetId)
3977 if (datasetIds == null)
3979 datasetIds = new Hashtable();
3982 if (datasetIds.containsKey(datasetId))
3984 return (Alignment) datasetIds.get(datasetId);
3989 private void addDatasetRef(String datasetId, Alignment dataset)
3991 if (datasetIds == null)
3993 datasetIds = new Hashtable();
3995 datasetIds.put(datasetId, dataset);
3999 * make a new dataset ID for this jalview dataset alignment
4004 private String getDatasetIdRef(jalview.datamodel.Alignment dataset)
4006 if (dataset.getDataset() != null)
4008 warn("Serious issue! Dataset Object passed to getDatasetIdRef is not a Jalview DATASET alignment...");
4010 String datasetId = makeHashCode(dataset, null);
4011 if (datasetId == null)
4013 // make a new datasetId and record it
4014 if (dataset2Ids == null)
4016 dataset2Ids = new IdentityHashMap();
4020 datasetId = (String) dataset2Ids.get(dataset);
4022 if (datasetId == null)
4024 datasetId = "ds" + dataset2Ids.size() + 1;
4025 dataset2Ids.put(dataset, datasetId);
4031 private void addDBRefs(SequenceI datasetSequence, Sequence sequence)
4033 for (int d = 0; d < sequence.getDBRefCount(); d++)
4035 DBRef dr = sequence.getDBRef(d);
4036 jalview.datamodel.DBRefEntry entry = new jalview.datamodel.DBRefEntry(
4037 sequence.getDBRef(d).getSource(), sequence.getDBRef(d)
4038 .getVersion(), sequence.getDBRef(d).getAccessionId());
4039 if (dr.getMapping() != null)
4041 entry.setMap(addMapping(dr.getMapping()));
4043 datasetSequence.addDBRef(entry);
4047 private jalview.datamodel.Mapping addMapping(Mapping m)
4049 SequenceI dsto = null;
4050 // Mapping m = dr.getMapping();
4051 int fr[] = new int[m.getMapListFromCount() * 2];
4052 Enumeration f = m.enumerateMapListFrom();
4053 for (int _i = 0; f.hasMoreElements(); _i += 2)
4055 MapListFrom mf = (MapListFrom) f.nextElement();
4056 fr[_i] = mf.getStart();
4057 fr[_i + 1] = mf.getEnd();
4059 int fto[] = new int[m.getMapListToCount() * 2];
4060 f = m.enumerateMapListTo();
4061 for (int _i = 0; f.hasMoreElements(); _i += 2)
4063 MapListTo mf = (MapListTo) f.nextElement();
4064 fto[_i] = mf.getStart();
4065 fto[_i + 1] = mf.getEnd();
4067 jalview.datamodel.Mapping jmap = new jalview.datamodel.Mapping(dsto,
4068 fr, fto, (int) m.getMapFromUnit(), (int) m.getMapToUnit());
4069 if (m.getMappingChoice() != null)
4071 MappingChoice mc = m.getMappingChoice();
4072 if (mc.getDseqFor() != null)
4074 String dsfor = "" + mc.getDseqFor();
4075 if (seqRefIds.containsKey(dsfor))
4080 jmap.setTo((SequenceI) seqRefIds.get(dsfor));
4084 frefedSequence.add(new Object[]
4091 * local sequence definition
4093 Sequence ms = mc.getSequence();
4094 jalview.datamodel.Sequence djs = null;
4095 String sqid = ms.getDsseqid();
4096 if (sqid != null && sqid.length() > 0)
4099 * recover dataset sequence
4101 djs = (jalview.datamodel.Sequence) seqRefIds.get(sqid);
4106 .println("Warning - making up dataset sequence id for DbRef sequence map reference");
4107 sqid = ((Object) ms).toString(); // make up a new hascode for
4108 // undefined dataset sequence hash
4109 // (unlikely to happen)
4115 * make a new dataset sequence and add it to refIds hash
4117 djs = new jalview.datamodel.Sequence(ms.getName(),
4119 djs.setStart(jmap.getMap().getToLowest());
4120 djs.setEnd(jmap.getMap().getToHighest());
4121 djs.setVamsasId(uniqueSetSuffix + sqid);
4123 seqRefIds.put(sqid, djs);
4126 jalview.bin.Cache.log.debug("about to recurse on addDBRefs.");
4135 public jalview.gui.AlignmentPanel copyAlignPanel(AlignmentPanel ap,
4136 boolean keepSeqRefs)
4139 jalview.schemabinding.version2.JalviewModel jm = SaveState(ap, null,
4145 jm.getJalviewModelSequence().getViewport(0).setSequenceSetId(null);
4149 uniqueSetSuffix = "";
4150 jm.getJalviewModelSequence().getViewport(0).setId(null); // we don't
4155 if (this.frefedSequence == null)
4157 frefedSequence = new Vector();
4160 viewportsAdded = new Hashtable();
4162 AlignFrame af = LoadFromObject(jm, null, false, null);
4163 af.alignPanels.clear();
4164 af.closeMenuItem_actionPerformed(true);
4167 * if(ap.av.getAlignment().getAlignmentAnnotation()!=null) { for(int i=0;
4168 * i<ap.av.getAlignment().getAlignmentAnnotation().length; i++) {
4169 * if(!ap.av.getAlignment().getAlignmentAnnotation()[i].autoCalculated) {
4170 * af.alignPanel.av.getAlignment().getAlignmentAnnotation()[i] =
4171 * ap.av.getAlignment().getAlignmentAnnotation()[i]; } } }
4174 return af.alignPanel;
4178 * flag indicating if hashtables should be cleared on finalization TODO this
4179 * flag may not be necessary
4181 private final boolean _cleartables = true;
4183 private Hashtable jvids2vobj;
4188 * @see java.lang.Object#finalize()
4191 protected void finalize() throws Throwable
4193 // really make sure we have no buried refs left.
4198 this.seqRefIds = null;
4199 this.seqsToIds = null;
4203 private void warn(String msg)
4208 private void warn(String msg, Exception e)
4210 if (Cache.log != null)
4214 Cache.log.warn(msg, e);
4218 Cache.log.warn(msg);
4223 System.err.println("Warning: " + msg);
4226 e.printStackTrace();
4231 private void debug(String string)
4233 debug(string, null);
4236 private void debug(String msg, Exception e)
4238 if (Cache.log != null)
4242 Cache.log.debug(msg, e);
4246 Cache.log.debug(msg);
4251 System.err.println("Warning: " + msg);
4254 e.printStackTrace();
4260 * set the object to ID mapping tables used to write/recover objects and XML
4261 * ID strings for the jalview project. If external tables are provided then
4262 * finalize and clearSeqRefs will not clear the tables when the Jalview2XML
4263 * object goes out of scope. - also populates the datasetIds hashtable with
4264 * alignment objects containing dataset sequences
4267 * Map from ID strings to jalview datamodel
4269 * Map from jalview datamodel to ID strings
4273 public void setObjectMappingTables(Hashtable vobj2jv,
4274 IdentityHashMap jv2vobj)
4276 this.jv2vobj = jv2vobj;
4277 this.vobj2jv = vobj2jv;
4278 Iterator ds = jv2vobj.keySet().iterator();
4280 while (ds.hasNext())
4282 Object jvobj = ds.next();
4283 id = jv2vobj.get(jvobj).toString();
4284 if (jvobj instanceof jalview.datamodel.Alignment)
4286 if (((jalview.datamodel.Alignment) jvobj).getDataset() == null)
4288 addDatasetRef(id, (jalview.datamodel.Alignment) jvobj);
4291 else if (jvobj instanceof jalview.datamodel.Sequence)
4293 // register sequence object so the XML parser can recover it.
4294 if (seqRefIds == null)
4296 seqRefIds = new Hashtable();
4298 if (seqsToIds == null)
4300 seqsToIds = new IdentityHashMap();
4302 seqRefIds.put(jv2vobj.get(jvobj).toString(), jvobj);
4303 seqsToIds.put(jvobj, id);
4305 else if (jvobj instanceof jalview.datamodel.AlignmentAnnotation)
4307 if (annotationIds == null)
4309 annotationIds = new Hashtable();
4312 annotationIds.put(anid = jv2vobj.get(jvobj).toString(), jvobj);
4313 jalview.datamodel.AlignmentAnnotation jvann = (jalview.datamodel.AlignmentAnnotation) jvobj;
4314 if (jvann.annotationId == null)
4316 jvann.annotationId = anid;
4318 if (!jvann.annotationId.equals(anid))
4320 // TODO verify that this is the correct behaviour
4321 this.warn("Overriding Annotation ID for " + anid
4322 + " from different id : " + jvann.annotationId);
4323 jvann.annotationId = anid;
4326 else if (jvobj instanceof String)
4328 if (jvids2vobj == null)
4330 jvids2vobj = new Hashtable();
4331 jvids2vobj.put(jvobj, jv2vobj.get(jvobj).toString());
4335 Cache.log.debug("Ignoring " + jvobj.getClass() + " (ID = " + id);
4340 * set the uniqueSetSuffix used to prefix/suffix object IDs for jalview
4341 * objects created from the project archive. If string is null (default for
4342 * construction) then suffix will be set automatically.
4346 public void setUniqueSetSuffix(String string)
4348 uniqueSetSuffix = string;
4353 * uses skipList2 as the skipList for skipping views on sequence sets
4354 * associated with keys in the skipList
4358 public void setSkipList(Hashtable skipList2)
4360 skipList = skipList2;