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().getDataset());
352 if (!dsses.containsKey(dssid))
354 dsses.put(dssid, af);
361 writeDatasetFor(dsses, ""+jout.hashCode()+" "+uniqueSetSuffix, jout);
366 } catch (Exception foo)
371 } catch (Exception ex)
373 // TODO: inform user of the problem - they need to know if their data was
375 if (errorMessage == null)
377 errorMessage = "Couldn't write Jalview Archive - see error output for details";
379 ex.printStackTrace();
383 // USE THIS METHOD TO SAVE A SINGLE ALIGNMENT WINDOW
384 public boolean SaveAlignment(AlignFrame af, String jarFile,
389 int ap, apSize = af.alignPanels.size();
390 FileOutputStream fos = new FileOutputStream(jarFile);
391 JarOutputStream jout = new JarOutputStream(fos);
392 Hashtable<String,AlignFrame> dsses = new Hashtable<String,AlignFrame>();
393 for (ap = 0; ap < apSize; ap++)
395 AlignmentPanel apanel = (AlignmentPanel) af.alignPanels
397 String jfileName = apSize == 1 ? fileName : fileName + ap;
398 if (!jfileName.endsWith(".xml"))
400 jfileName = jfileName + ".xml";
402 SaveState(apanel, jfileName, jout);
403 String dssid = getDatasetIdRef(af.getViewport().getAlignment().getDataset());
404 if (!dsses.containsKey(dssid))
406 dsses.put(dssid, af);
409 writeDatasetFor(dsses, fileName, jout);
413 } catch (Exception foo)
419 } catch (Exception ex)
421 errorMessage = "Couldn't Write alignment view to Jalview Archive - see error output for details";
422 ex.printStackTrace();
427 private void writeDatasetFor(Hashtable<String, AlignFrame> dsses,
428 String fileName, JarOutputStream jout)
431 for (String dssids:dsses.keySet())
433 AlignFrame _af = dsses.get(dssids);
434 String jfileName = fileName + " Dataset for "+ _af.getTitle();
435 if (!jfileName.endsWith(".xml"))
437 jfileName = jfileName + ".xml";
439 SaveState(_af.alignPanel, jfileName, true, jout);
444 * create a JalviewModel from an algnment view and marshall it to a
448 * panel to create jalview model for
450 * name of alignment panel written to output stream
456 public JalviewModel SaveState(AlignmentPanel ap, String fileName,
457 JarOutputStream jout)
459 return SaveState(ap, fileName, false,jout);
462 * create a JalviewModel from an algnment view and marshall it to a
466 * panel to create jalview model for
468 * name of alignment panel written to output stream
470 * when true, only write the dataset for the alignment, not the data associated with the view.
476 public JalviewModel SaveState(AlignmentPanel ap, String fileName, boolean storeDS,
477 JarOutputStream jout)
480 Vector jmolViewIds = new Vector(); //
481 Vector userColours = new Vector();
483 AlignViewport av = ap.av;
485 JalviewModel object = new JalviewModel();
486 object.setVamsasModel(new jalview.schemabinding.version2.VamsasModel());
488 object.setCreationDate(new java.util.Date(System.currentTimeMillis()));
489 object.setVersion(jalview.bin.Cache.getDefault("VERSION","Development Build"));
491 jalview.datamodel.AlignmentI jal = av.getAlignment();
493 if (av.hasHiddenRows())
495 jal = jal.getHiddenSequences().getFullAlignment();
498 SequenceSet vamsasSet = new SequenceSet();
500 JalviewModelSequence jms = new JalviewModelSequence();
502 vamsasSet.setGapChar(jal.getGapCharacter() + "");
504 if (jal.getDataset() != null)
506 // dataset id is the dataset's hashcode
507 vamsasSet.setDatasetId(getDatasetIdRef(jal.getDataset()));
510 // switch jal and the dataset
511 jal = jal.getDataset();
514 if (jal.getProperties() != null)
516 Enumeration en = jal.getProperties().keys();
517 while (en.hasMoreElements())
519 String key = en.nextElement().toString();
520 SequenceSetProperties ssp = new SequenceSetProperties();
522 ssp.setValue(jal.getProperties().get(key).toString());
523 vamsasSet.addSequenceSetProperties(ssp);
528 Set<String> calcIdSet = new HashSet<String>();
532 jalview.datamodel.SequenceI jds,jdatasq;
533 for (int i = 0; i < jal.getHeight(); i++)
535 jds = jal.getSequenceAt(i);
536 jdatasq=jds.getDatasetSequence() == null ? jds : jds.getDatasetSequence();
539 if (seqRefIds.get(id) != null)
541 // This happens for two reasons: 1. multiple views are being serialised.
542 // 2. the hashCode has collided with another sequence's code. This DOES
543 // HAPPEN! (PF00072.15.stk does this)
544 // JBPNote: Uncomment to debug writing out of files that do not read
545 // back in due to ArrayOutOfBoundExceptions.
546 // System.err.println("vamsasSeq backref: "+id+"");
547 // System.err.println(jds.getName()+"
548 // "+jds.getStart()+"-"+jds.getEnd()+" "+jds.getSequenceAsString());
549 // System.err.println("Hashcode: "+seqHash(jds));
550 // SequenceI rsq = (SequenceI) seqRefIds.get(id + "");
551 // System.err.println(rsq.getName()+"
552 // "+rsq.getStart()+"-"+rsq.getEnd()+" "+rsq.getSequenceAsString());
553 // System.err.println("Hashcode: "+seqHash(rsq));
557 vamsasSeq = createVamsasSequence(id, jds);
558 vamsasSet.addSequence(vamsasSeq);
559 seqRefIds.put(id, jds);
563 jseq.setStart(jds.getStart());
564 jseq.setEnd(jds.getEnd());
565 jseq.setColour(av.getSequenceColour(jds).getRGB());
567 jseq.setId(id); // jseq id should be a string not a number
570 // Store any sequences this sequence represents
571 if (av.hasHiddenRows())
573 jseq.setHidden(av.getAlignment().getHiddenSequences()
576 if (av.isHiddenRepSequence(jal.getSequenceAt(i)))
578 jalview.datamodel.SequenceI[] reps = av
579 .getRepresentedSequences(jal.getSequenceAt(i))
580 .getSequencesInOrder(jal);
582 for (int h = 0; h < reps.length; h++)
584 if (reps[h] != jal.getSequenceAt(i))
586 jseq.addHiddenSequences(jal.findIndex(reps[h]));
593 if (jdatasq.getSequenceFeatures() != null)
595 jalview.datamodel.SequenceFeature[] sf = jdatasq
596 .getSequenceFeatures();
598 while (index < sf.length)
600 Features features = new Features();
602 features.setBegin(sf[index].getBegin());
603 features.setEnd(sf[index].getEnd());
604 features.setDescription(sf[index].getDescription());
605 features.setType(sf[index].getType());
606 features.setFeatureGroup(sf[index].getFeatureGroup());
607 features.setScore(sf[index].getScore());
608 if (sf[index].links != null)
610 for (int l = 0; l < sf[index].links.size(); l++)
612 OtherData keyValue = new OtherData();
613 keyValue.setKey("LINK_" + l);
614 keyValue.setValue(sf[index].links.elementAt(l).toString());
615 features.addOtherData(keyValue);
618 if (sf[index].otherDetails != null)
621 Enumeration keys = sf[index].otherDetails.keys();
622 while (keys.hasMoreElements())
624 key = keys.nextElement().toString();
625 OtherData keyValue = new OtherData();
626 keyValue.setKey(key);
627 keyValue.setValue(sf[index].otherDetails.get(key).toString());
628 features.addOtherData(keyValue);
632 jseq.addFeatures(features);
637 if (jdatasq.getPDBId() != null)
639 Enumeration en = jdatasq.getPDBId().elements();
640 while (en.hasMoreElements())
642 Pdbids pdb = new Pdbids();
643 jalview.datamodel.PDBEntry entry = (jalview.datamodel.PDBEntry) en
646 pdb.setId(entry.getId());
647 pdb.setType(entry.getType());
649 // store any JMol views associated with this seqeunce
650 // this section copes with duplicate entries in the project, so a
651 // dataset only view *should* be coped with sensibly
653 // This must have been loaded, is it still visible?
654 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
655 String matchedFile = null;
656 for (int f = frames.length - 1; f > -1; f--)
658 if (frames[f] instanceof AppJmol)
660 jmol = (AppJmol) frames[f];
661 for (int peid = 0; peid < jmol.jmb.pdbentry.length; peid++)
663 if (!jmol.jmb.pdbentry[peid].getId().equals(entry.getId())
664 && !(entry.getId().length() > 4 && entry
668 jmol.jmb.pdbentry[peid].getId()
671 if (matchedFile == null)
673 matchedFile = jmol.jmb.pdbentry[peid].getFile();
675 else if (!matchedFile.equals(jmol.jmb.pdbentry[peid]
679 .warn("Probably lost some PDB-Sequence mappings for this structure file (which apparently has same PDB Entry code): "
680 + jmol.jmb.pdbentry[peid].getFile());
684 // can get at it if the ID
685 // match is ambiguous (e.g.
687 String statestring = jmol.jmb.viewer.getStateInfo();
689 for (int smap = 0; smap < jmol.jmb.sequence[peid].length; smap++)
691 // if (jal.findIndex(jmol.jmb.sequence[peid][smap]) > -1)
692 if (jds == jmol.jmb.sequence[peid][smap])
694 StructureState state = new StructureState();
695 state.setVisible(true);
696 state.setXpos(jmol.getX());
697 state.setYpos(jmol.getY());
698 state.setWidth(jmol.getWidth());
699 state.setHeight(jmol.getHeight());
700 state.setViewId(jmol.getViewId());
701 state.setAlignwithAlignPanel(jmol.isUsedforaligment(ap));
702 state.setColourwithAlignPanel(jmol
703 .isUsedforcolourby(ap));
704 state.setColourByJmol(jmol.isColouredByJmol());
705 if (!jmolViewIds.contains(state.getViewId()))
707 // Make sure we only store a Jmol state once in each XML
709 jmolViewIds.addElement(state.getViewId());
710 state.setContent(statestring.replaceAll("\n", ""));
714 state.setContent("# duplicate state");
716 pdb.addStructureState(state);
724 if (matchedFile != null || entry.getFile() != null)
726 if (entry.getFile() != null)
729 matchedFile = entry.getFile();
731 pdb.setFile(matchedFile); // entry.getFile());
732 if (pdbfiles == null)
734 pdbfiles = new Vector();
737 if (!pdbfiles.contains(entry.getId()))
739 pdbfiles.addElement(entry.getId());
742 File file = new File(matchedFile);
743 if (file.exists() && jout != null)
745 byte[] data = new byte[(int) file.length()];
746 jout.putNextEntry(new JarEntry(entry.getId()));
747 DataInputStream dis = new DataInputStream(
748 new FileInputStream(file));
751 DataOutputStream dout = new DataOutputStream(jout);
752 dout.write(data, 0, data.length);
756 } catch (Exception ex)
758 ex.printStackTrace();
764 if (entry.getProperty() != null)
766 PdbentryItem item = new PdbentryItem();
767 Hashtable properties = entry.getProperty();
768 Enumeration en2 = properties.keys();
769 while (en2.hasMoreElements())
771 Property prop = new Property();
772 String key = en2.nextElement().toString();
774 prop.setValue(properties.get(key).toString());
775 item.addProperty(prop);
777 pdb.addPdbentryItem(item);
787 if (!storeDS && av.hasHiddenRows())
789 jal = av.getAlignment();
792 if (jal.getCodonFrames() != null && jal.getCodonFrames().length > 0)
794 jalview.datamodel.AlignedCodonFrame[] jac = jal.getCodonFrames();
795 for (int i = 0; i < jac.length; i++)
797 AlcodonFrame alc = new AlcodonFrame();
798 vamsasSet.addAlcodonFrame(alc);
799 for (int p = 0; p < jac[i].aaWidth; p++)
801 Alcodon cmap = new Alcodon();
802 if (jac[i].codons[p] != null)
804 // Null codons indicate a gapped column in the translated peptide
806 cmap.setPos1(jac[i].codons[p][0]);
807 cmap.setPos2(jac[i].codons[p][1]);
808 cmap.setPos3(jac[i].codons[p][2]);
810 alc.addAlcodon(cmap);
812 if (jac[i].getProtMappings() != null
813 && jac[i].getProtMappings().length > 0)
815 SequenceI[] dnas = jac[i].getdnaSeqs();
816 jalview.datamodel.Mapping[] pmaps = jac[i].getProtMappings();
817 for (int m = 0; m < pmaps.length; m++)
819 AlcodMap alcmap = new AlcodMap();
820 alcmap.setDnasq(seqHash(dnas[m]));
821 alcmap.setMapping(createVamsasMapping(pmaps[m], dnas[m], null,
823 alc.addAlcodMap(alcmap);
830 // /////////////////////////////////
831 if (!storeDS && av.currentTree != null)
833 // FIND ANY ASSOCIATED TREES
834 // NOT IMPLEMENTED FOR HEADLESS STATE AT PRESENT
835 if (Desktop.desktop != null)
837 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
839 for (int t = 0; t < frames.length; t++)
841 if (frames[t] instanceof TreePanel)
843 TreePanel tp = (TreePanel) frames[t];
845 if (tp.treeCanvas.av.getAlignment() == jal)
847 Tree tree = new Tree();
848 tree.setTitle(tp.getTitle());
849 tree.setCurrentTree((av.currentTree == tp.getTree()));
850 tree.setNewick(tp.getTree().toString());
851 tree.setThreshold(tp.treeCanvas.threshold);
853 tree.setFitToWindow(tp.fitToWindow.getState());
854 tree.setFontName(tp.getTreeFont().getName());
855 tree.setFontSize(tp.getTreeFont().getSize());
856 tree.setFontStyle(tp.getTreeFont().getStyle());
857 tree.setMarkUnlinked(tp.placeholdersMenu.getState());
859 tree.setShowBootstrap(tp.bootstrapMenu.getState());
860 tree.setShowDistances(tp.distanceMenu.getState());
862 tree.setHeight(tp.getHeight());
863 tree.setWidth(tp.getWidth());
864 tree.setXpos(tp.getX());
865 tree.setYpos(tp.getY());
866 tree.setId(makeHashCode(tp, null));
875 * store forward refs from an annotationRow to any groups
877 IdentityHashMap groupRefs = new IdentityHashMap();
880 for (SequenceI sq:jal.getSequences())
882 // Store annotation on dataset sequences only
883 jalview.datamodel.AlignmentAnnotation[] aa = sq.getAnnotation();
884 if (aa!=null && aa.length>0)
886 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
891 if (jal.getAlignmentAnnotation() != null)
893 // Store the annotation shown on the alignment.
894 jalview.datamodel.AlignmentAnnotation[] aa = jal
895 .getAlignmentAnnotation();
896 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
901 if (jal.getGroups() != null)
903 JGroup[] groups = new JGroup[jal.getGroups().size()];
905 for (jalview.datamodel.SequenceGroup sg : jal.getGroups())
907 groups[++i] = new JGroup();
909 groups[i].setStart(sg.getStartRes());
910 groups[i].setEnd(sg.getEndRes());
911 groups[i].setName(sg.getName());
912 if (groupRefs.containsKey(sg))
914 // group has references so set it's ID field
915 groups[i].setId(groupRefs.get(sg).toString());
919 if (sg.cs.conservationApplied())
921 groups[i].setConsThreshold(sg.cs.getConservationInc());
923 if (sg.cs instanceof jalview.schemes.UserColourScheme)
925 groups[i].setColour(SetUserColourScheme(sg.cs, userColours,
931 .setColour(ColourSchemeProperty.getColourName(sg.cs));
934 else if (sg.cs instanceof jalview.schemes.AnnotationColourGradient)
937 .setColour(ColourSchemeProperty
938 .getColourName(((jalview.schemes.AnnotationColourGradient) sg.cs)
941 else if (sg.cs instanceof jalview.schemes.UserColourScheme)
944 .setColour(SetUserColourScheme(sg.cs, userColours, jms));
948 groups[i].setColour(ColourSchemeProperty.getColourName(sg.cs));
951 groups[i].setPidThreshold(sg.cs.getThreshold());
954 groups[i].setOutlineColour(sg.getOutlineColour().getRGB());
955 groups[i].setDisplayBoxes(sg.getDisplayBoxes());
956 groups[i].setDisplayText(sg.getDisplayText());
957 groups[i].setColourText(sg.getColourText());
958 groups[i].setTextCol1(sg.textColour.getRGB());
959 groups[i].setTextCol2(sg.textColour2.getRGB());
960 groups[i].setTextColThreshold(sg.thresholdTextColour);
961 groups[i].setShowUnconserved(sg.getShowNonconserved());
962 groups[i].setIgnoreGapsinConsensus(sg.getIgnoreGapsConsensus());
963 groups[i].setShowConsensusHistogram(sg.isShowConsensusHistogram());
964 groups[i].setShowSequenceLogo(sg.isShowSequenceLogo());
965 groups[i].setNormaliseSequenceLogo(sg.isNormaliseSequenceLogo());
966 for (int s = 0; s < sg.getSize(); s++)
968 jalview.datamodel.Sequence seq = (jalview.datamodel.Sequence) sg
970 groups[i].addSeq(seqHash(seq));
974 jms.setJGroup(groups);
978 // /////////SAVE VIEWPORT
979 Viewport view = new Viewport();
980 view.setTitle(ap.alignFrame.getTitle());
981 view.setSequenceSetId(makeHashCode(av.getSequenceSetId(),
982 av.getSequenceSetId()));
983 view.setId(av.getViewId());
984 view.setViewName(av.viewName);
985 view.setGatheredViews(av.gatherViewsHere);
987 if (ap.av.explodedPosition != null)
989 view.setXpos(av.explodedPosition.x);
990 view.setYpos(av.explodedPosition.y);
991 view.setWidth(av.explodedPosition.width);
992 view.setHeight(av.explodedPosition.height);
996 view.setXpos(ap.alignFrame.getBounds().x);
997 view.setYpos(ap.alignFrame.getBounds().y);
998 view.setWidth(ap.alignFrame.getBounds().width);
999 view.setHeight(ap.alignFrame.getBounds().height);
1002 view.setStartRes(av.startRes);
1003 view.setStartSeq(av.startSeq);
1005 if (av.getGlobalColourScheme() instanceof jalview.schemes.UserColourScheme)
1007 view.setBgColour(SetUserColourScheme(av.getGlobalColourScheme(),
1010 else if (av.getGlobalColourScheme() instanceof jalview.schemes.AnnotationColourGradient)
1012 jalview.schemes.AnnotationColourGradient acg = (jalview.schemes.AnnotationColourGradient) av
1013 .getGlobalColourScheme();
1015 AnnotationColours ac = new AnnotationColours();
1016 ac.setAboveThreshold(acg.getAboveThreshold());
1017 ac.setThreshold(acg.getAnnotationThreshold());
1018 ac.setAnnotation(acg.getAnnotation());
1019 if (acg.getBaseColour() instanceof jalview.schemes.UserColourScheme)
1021 ac.setColourScheme(SetUserColourScheme(acg.getBaseColour(),
1026 ac.setColourScheme(ColourSchemeProperty.getColourName(acg
1030 ac.setMaxColour(acg.getMaxColour().getRGB());
1031 ac.setMinColour(acg.getMinColour().getRGB());
1032 ac.setPerSequence(acg.isSeqAssociated());
1033 ac.setPredefinedColours(acg.isPredefinedColours());
1034 view.setAnnotationColours(ac);
1035 view.setBgColour("AnnotationColourGradient");
1039 view.setBgColour(ColourSchemeProperty.getColourName(av
1040 .getGlobalColourScheme()));
1043 ColourSchemeI cs = av.getGlobalColourScheme();
1047 if (cs.conservationApplied())
1049 view.setConsThreshold(cs.getConservationInc());
1050 if (cs instanceof jalview.schemes.UserColourScheme)
1052 view.setBgColour(SetUserColourScheme(cs, userColours, jms));
1056 if (cs instanceof ResidueColourScheme)
1058 view.setPidThreshold(cs.getThreshold());
1062 view.setConservationSelected(av.getConservationSelected());
1063 view.setPidSelected(av.getAbovePIDThreshold());
1064 view.setFontName(av.font.getName());
1065 view.setFontSize(av.font.getSize());
1066 view.setFontStyle(av.font.getStyle());
1067 view.setRenderGaps(av.renderGaps);
1068 view.setShowAnnotation(av.getShowAnnotation());
1069 view.setShowBoxes(av.getShowBoxes());
1070 view.setShowColourText(av.getColourText());
1071 view.setShowFullId(av.getShowJVSuffix());
1072 view.setRightAlignIds(av.rightAlignIds);
1073 view.setShowSequenceFeatures(av.showSequenceFeatures);
1074 view.setShowText(av.getShowText());
1075 view.setShowUnconserved(av.getShowUnconserved());
1076 view.setWrapAlignment(av.getWrapAlignment());
1077 view.setTextCol1(av.textColour.getRGB());
1078 view.setTextCol2(av.textColour2.getRGB());
1079 view.setTextColThreshold(av.thresholdTextColour);
1080 view.setShowConsensusHistogram(av.isShowConsensusHistogram());
1081 view.setShowSequenceLogo(av.isShowSequenceLogo());
1082 view.setNormaliseSequenceLogo(av.isNormaliseSequenceLogo());
1083 view.setShowGroupConsensus(av.isShowGroupConsensus());
1084 view.setShowGroupConservation(av.isShowGroupConservation());
1085 view.setShowNPfeatureTooltip(av.isShowNpFeats());
1086 view.setShowDbRefTooltip(av.isShowDbRefs());
1087 view.setFollowHighlight(av.followHighlight);
1088 view.setFollowSelection(av.followSelection);
1089 view.setIgnoreGapsinConsensus(av.getIgnoreGapsConsensus());
1090 if (av.featuresDisplayed != null)
1092 jalview.schemabinding.version2.FeatureSettings fs = new jalview.schemabinding.version2.FeatureSettings();
1094 String[] renderOrder = ap.seqPanel.seqCanvas.getFeatureRenderer().renderOrder;
1096 Vector settingsAdded = new Vector();
1097 Object gstyle = null;
1098 GraduatedColor gcol = null;
1099 if (renderOrder != null)
1101 for (int ro = 0; ro < renderOrder.length; ro++)
1103 gstyle = ap.seqPanel.seqCanvas.getFeatureRenderer()
1104 .getFeatureStyle(renderOrder[ro]);
1105 Setting setting = new Setting();
1106 setting.setType(renderOrder[ro]);
1107 if (gstyle instanceof GraduatedColor)
1109 gcol = (GraduatedColor) gstyle;
1110 setting.setColour(gcol.getMaxColor().getRGB());
1111 setting.setMincolour(gcol.getMinColor().getRGB());
1112 setting.setMin(gcol.getMin());
1113 setting.setMax(gcol.getMax());
1114 setting.setColourByLabel(gcol.isColourByLabel());
1115 setting.setAutoScale(gcol.isAutoScale());
1116 setting.setThreshold(gcol.getThresh());
1117 setting.setThreshstate(gcol.getThreshType());
1121 setting.setColour(ap.seqPanel.seqCanvas.getFeatureRenderer()
1122 .getColour(renderOrder[ro]).getRGB());
1125 setting.setDisplay(av.featuresDisplayed
1126 .containsKey(renderOrder[ro]));
1127 float rorder = ap.seqPanel.seqCanvas.getFeatureRenderer()
1128 .getOrder(renderOrder[ro]);
1131 setting.setOrder(rorder);
1133 fs.addSetting(setting);
1134 settingsAdded.addElement(renderOrder[ro]);
1138 // Make sure we save none displayed feature settings
1139 Iterator en = ap.seqPanel.seqCanvas.getFeatureRenderer().featureColours
1140 .keySet().iterator();
1141 while (en.hasNext())
1143 String key = en.next().toString();
1144 if (settingsAdded.contains(key))
1149 Setting setting = new Setting();
1150 setting.setType(key);
1151 setting.setColour(ap.seqPanel.seqCanvas.getFeatureRenderer()
1152 .getColour(key).getRGB());
1154 setting.setDisplay(false);
1155 float rorder = ap.seqPanel.seqCanvas.getFeatureRenderer()
1159 setting.setOrder(rorder);
1161 fs.addSetting(setting);
1162 settingsAdded.addElement(key);
1164 en = ap.seqPanel.seqCanvas.getFeatureRenderer().featureGroups
1165 .keySet().iterator();
1166 Vector groupsAdded = new Vector();
1167 while (en.hasNext())
1169 String grp = en.next().toString();
1170 if (groupsAdded.contains(grp))
1174 Group g = new Group();
1176 g.setDisplay(((Boolean) ap.seqPanel.seqCanvas
1177 .getFeatureRenderer().featureGroups.get(grp))
1180 groupsAdded.addElement(grp);
1182 jms.setFeatureSettings(fs);
1186 if (av.hasHiddenColumns())
1188 if (av.getColumnSelection() == null
1189 || av.getColumnSelection().getHiddenColumns() == null)
1191 warn("REPORT BUG: avoided null columnselection bug (DMAM reported). Please contact Jim about this.");
1195 for (int c = 0; c < av.getColumnSelection().getHiddenColumns()
1198 int[] region = (int[]) av.getColumnSelection()
1199 .getHiddenColumns().elementAt(c);
1200 HiddenColumns hc = new HiddenColumns();
1201 hc.setStart(region[0]);
1202 hc.setEnd(region[1]);
1203 view.addHiddenColumns(hc);
1207 if (calcIdSet.size() > 0)
1209 for (String calcId : calcIdSet)
1211 if (calcId.trim().length() > 0)
1213 CalcIdParam cidp = createCalcIdParam(calcId, av);
1214 // Some calcIds have no parameters.
1217 view.addCalcIdParam(cidp);
1223 jms.addViewport(view);
1225 object.setJalviewModelSequence(jms);
1226 object.getVamsasModel().addSequenceSet(vamsasSet);
1228 if (jout != null && fileName != null)
1230 // We may not want to write the object to disk,
1231 // eg we can copy the alignViewport to a new view object
1232 // using save and then load
1235 JarEntry entry = new JarEntry(fileName);
1236 jout.putNextEntry(entry);
1237 PrintWriter pout = new PrintWriter(new OutputStreamWriter(jout,
1239 org.exolab.castor.xml.Marshaller marshaller = new org.exolab.castor.xml.Marshaller(
1241 marshaller.marshal(object);
1244 } catch (Exception ex)
1246 // TODO: raise error in GUI if marshalling failed.
1247 ex.printStackTrace();
1253 private void storeAlignmentAnnotation(AlignmentAnnotation[] aa, IdentityHashMap groupRefs, AlignmentViewport av, Set<String> calcIdSet, boolean storeDS, SequenceSet vamsasSet)
1256 for (int i = 0; i < aa.length; i++)
1258 Annotation an = new Annotation();
1260 if (aa[i].annotationId != null)
1262 annotationIds.put(aa[i].annotationId, aa[i]);
1265 an.setId(aa[i].annotationId);
1267 an.setVisible(aa[i].visible);
1269 an.setDescription(aa[i].description);
1271 if (aa[i].sequenceRef != null)
1273 // TODO later annotation sequenceRef should be the XML ID of the
1274 // sequence rather than its display name
1275 an.setSequenceRef(aa[i].sequenceRef.getName());
1277 if (aa[i].groupRef != null)
1279 Object groupIdr = groupRefs.get(aa[i].groupRef);
1280 if (groupIdr == null)
1282 // make a locally unique String
1283 groupRefs.put(aa[i].groupRef,
1284 groupIdr = ("" + System.currentTimeMillis()
1285 + aa[i].groupRef.getName() + groupRefs.size()));
1287 an.setGroupRef(groupIdr.toString());
1290 // store all visualization attributes for annotation
1291 an.setGraphHeight(aa[i].graphHeight);
1292 an.setCentreColLabels(aa[i].centreColLabels);
1293 an.setScaleColLabels(aa[i].scaleColLabel);
1294 an.setShowAllColLabels(aa[i].showAllColLabels);
1295 an.setBelowAlignment(aa[i].belowAlignment);
1297 if (aa[i].graph > 0)
1300 an.setGraphType(aa[i].graph);
1301 an.setGraphGroup(aa[i].graphGroup);
1302 if (aa[i].getThreshold() != null)
1304 ThresholdLine line = new ThresholdLine();
1305 line.setLabel(aa[i].getThreshold().label);
1306 line.setValue(aa[i].getThreshold().value);
1307 line.setColour(aa[i].getThreshold().colour.getRGB());
1308 an.setThresholdLine(line);
1316 an.setLabel(aa[i].label);
1318 if (aa[i] == av.getAlignmentQualityAnnot()
1319 || aa[i] == av.getAlignmentConservationAnnotation()
1320 || aa[i] == av.getAlignmentConsensusAnnotation()
1321 || aa[i].autoCalculated)
1323 // new way of indicating autocalculated annotation -
1324 an.setAutoCalculated(aa[i].autoCalculated);
1326 if (aa[i].hasScore())
1328 an.setScore(aa[i].getScore());
1331 if (aa[i].getCalcId() != null)
1333 calcIdSet.add(aa[i].getCalcId());
1334 an.setCalcId(aa[i].getCalcId());
1337 AnnotationElement ae;
1338 if (aa[i].annotations != null)
1340 an.setScoreOnly(false);
1341 for (int a = 0; a < aa[i].annotations.length; a++)
1343 if ((aa[i] == null) || (aa[i].annotations[a] == null))
1348 ae = new AnnotationElement();
1349 if (aa[i].annotations[a].description != null)
1350 ae.setDescription(aa[i].annotations[a].description);
1351 if (aa[i].annotations[a].displayCharacter != null)
1352 ae.setDisplayCharacter(aa[i].annotations[a].displayCharacter);
1354 if (!Float.isNaN(aa[i].annotations[a].value))
1355 ae.setValue(aa[i].annotations[a].value);
1358 if (aa[i].annotations[a].secondaryStructure != ' '
1359 && aa[i].annotations[a].secondaryStructure != '\0')
1360 ae.setSecondaryStructure(aa[i].annotations[a].secondaryStructure
1363 if (aa[i].annotations[a].colour != null
1364 && aa[i].annotations[a].colour != java.awt.Color.black)
1366 ae.setColour(aa[i].annotations[a].colour.getRGB());
1369 an.addAnnotationElement(ae);
1370 if (aa[i].autoCalculated)
1372 // only write one non-null entry into the annotation row -
1373 // sufficient to get the visualization attributes necessary to
1381 an.setScoreOnly(true);
1383 if (!storeDS || (storeDS && !aa[i].autoCalculated))
1385 // skip autocalculated annotation - these are only provided for alignments
1386 vamsasSet.addAnnotation(an);
1392 private CalcIdParam createCalcIdParam(String calcId, AlignViewport av)
1394 AutoCalcSetting settings = av.getCalcIdSettingsFor(calcId);
1395 if (settings != null)
1397 CalcIdParam vCalcIdParam = new CalcIdParam();
1398 vCalcIdParam.setCalcId(calcId);
1399 vCalcIdParam.addServiceURL(settings.getServiceURI());
1400 // generic URI allowing a third party to resolve another instance of the
1401 // service used for this calculation
1402 for (String urls : settings.getServiceURLs())
1404 vCalcIdParam.addServiceURL(urls);
1406 vCalcIdParam.setVersion("1.0");
1407 if (settings.getPreset() != null)
1409 WsParamSetI setting = settings.getPreset();
1410 vCalcIdParam.setName(setting.getName());
1411 vCalcIdParam.setDescription(setting.getDescription());
1415 vCalcIdParam.setName("");
1416 vCalcIdParam.setDescription("Last used parameters");
1418 // need to be able to recover 1) settings 2) user-defined presets or
1419 // recreate settings from preset 3) predefined settings provided by
1420 // service - or settings that can be transferred (or discarded)
1421 vCalcIdParam.setParameters(settings.getWsParamFile().replace("\n",
1423 vCalcIdParam.setAutoUpdate(settings.isAutoUpdate());
1424 // todo - decide if updateImmediately is needed for any projects.
1426 return vCalcIdParam;
1431 private boolean recoverCalcIdParam(CalcIdParam calcIdParam,
1434 if (calcIdParam.getVersion().equals("1.0"))
1436 Jws2Instance service = Jws2Discoverer.getDiscoverer()
1437 .getPreferredServiceFor(calcIdParam.getServiceURL());
1438 if (service != null)
1440 WsParamSetI parmSet = null;
1443 parmSet = service.getParamStore().parseServiceParameterFile(
1444 calcIdParam.getName(), calcIdParam.getDescription(),
1445 calcIdParam.getServiceURL(),
1446 calcIdParam.getParameters().replace("|\\n|", "\n"));
1447 } catch (IOException x)
1449 warn("Couldn't parse parameter data for "
1450 + calcIdParam.getCalcId(), x);
1453 List<ArgumentI> argList = null;
1454 if (calcIdParam.getName().length() > 0)
1456 parmSet = service.getParamStore()
1457 .getPreset(calcIdParam.getName());
1458 if (parmSet != null)
1460 // TODO : check we have a good match with settings in AACon -
1461 // otherwise we'll need to create a new preset
1466 argList = parmSet.getArguments();
1469 AAConSettings settings = new AAConSettings(
1470 calcIdParam.isAutoUpdate(), service, parmSet, argList);
1471 av.setCalcIdSettingsFor(calcIdParam.getCalcId(), settings,
1472 calcIdParam.isNeedsUpdate());
1477 warn("Cannot resolve a service for the parameters used in this project. Try configuring a JABAWS server.");
1481 throw new Error("Unsupported Version for calcIdparam "
1482 + calcIdParam.toString());
1486 * External mapping between jalview objects and objects yielding a valid and
1487 * unique object ID string. This is null for normal Jalview project IO, but
1488 * non-null when a jalview project is being read or written as part of a
1491 IdentityHashMap jv2vobj = null;
1494 * Construct a unique ID for jvobj using either existing bindings or if none
1495 * exist, the result of the hashcode call for the object.
1498 * jalview data object
1499 * @return unique ID for referring to jvobj
1501 private String makeHashCode(Object jvobj, String altCode)
1503 if (jv2vobj != null)
1505 Object id = jv2vobj.get(jvobj);
1508 return id.toString();
1510 // check string ID mappings
1511 if (jvids2vobj != null && jvobj instanceof String)
1513 id = jvids2vobj.get(jvobj);
1517 return id.toString();
1519 // give up and warn that something has gone wrong
1520 warn("Cannot find ID for object in external mapping : " + jvobj);
1526 * return local jalview object mapped to ID, if it exists
1530 * @return null or object bound to idcode
1532 private Object retrieveExistingObj(String idcode)
1534 if (idcode != null && vobj2jv != null)
1536 return vobj2jv.get(idcode);
1542 * binding from ID strings from external mapping table to jalview data model
1545 private Hashtable vobj2jv;
1547 private Sequence createVamsasSequence(String id, SequenceI jds)
1549 return createVamsasSequence(true, id, jds, null);
1552 private Sequence createVamsasSequence(boolean recurse, String id,
1553 SequenceI jds, SequenceI parentseq)
1555 Sequence vamsasSeq = new Sequence();
1556 vamsasSeq.setId(id);
1557 vamsasSeq.setName(jds.getName());
1558 vamsasSeq.setSequence(jds.getSequenceAsString());
1559 vamsasSeq.setDescription(jds.getDescription());
1560 jalview.datamodel.DBRefEntry[] dbrefs = null;
1561 if (jds.getDatasetSequence() != null)
1563 vamsasSeq.setDsseqid(seqHash(jds.getDatasetSequence()));
1564 if (jds.getDatasetSequence().getDBRef() != null)
1566 dbrefs = jds.getDatasetSequence().getDBRef();
1571 vamsasSeq.setDsseqid(id); // so we can tell which sequences really are
1572 // dataset sequences only
1573 dbrefs = jds.getDBRef();
1577 for (int d = 0; d < dbrefs.length; d++)
1579 DBRef dbref = new DBRef();
1580 dbref.setSource(dbrefs[d].getSource());
1581 dbref.setVersion(dbrefs[d].getVersion());
1582 dbref.setAccessionId(dbrefs[d].getAccessionId());
1583 if (dbrefs[d].hasMap())
1585 Mapping mp = createVamsasMapping(dbrefs[d].getMap(), parentseq,
1587 dbref.setMapping(mp);
1589 vamsasSeq.addDBRef(dbref);
1595 private Mapping createVamsasMapping(jalview.datamodel.Mapping jmp,
1596 SequenceI parentseq, SequenceI jds, boolean recurse)
1599 if (jmp.getMap() != null)
1603 jalview.util.MapList mlst = jmp.getMap();
1604 int r[] = mlst.getFromRanges();
1605 for (int s = 0; s < r.length; s += 2)
1607 MapListFrom mfrom = new MapListFrom();
1608 mfrom.setStart(r[s]);
1609 mfrom.setEnd(r[s + 1]);
1610 mp.addMapListFrom(mfrom);
1612 r = mlst.getToRanges();
1613 for (int s = 0; s < r.length; s += 2)
1615 MapListTo mto = new MapListTo();
1617 mto.setEnd(r[s + 1]);
1618 mp.addMapListTo(mto);
1620 mp.setMapFromUnit(mlst.getFromRatio());
1621 mp.setMapToUnit(mlst.getToRatio());
1622 if (jmp.getTo() != null)
1624 MappingChoice mpc = new MappingChoice();
1626 && (parentseq != jmp.getTo() || parentseq
1627 .getDatasetSequence() != jmp.getTo()))
1629 mpc.setSequence(createVamsasSequence(false, seqHash(jmp.getTo()),
1635 SequenceI ps = null;
1636 if (parentseq != jmp.getTo()
1637 && parentseq.getDatasetSequence() != jmp.getTo())
1639 // chaining dbref rather than a handshaking one
1640 jmpid = seqHash(ps = jmp.getTo());
1644 jmpid = seqHash(ps = parentseq);
1646 mpc.setDseqFor(jmpid);
1647 if (!seqRefIds.containsKey(mpc.getDseqFor()))
1649 jalview.bin.Cache.log.debug("creatign new DseqFor ID");
1650 seqRefIds.put(mpc.getDseqFor(), ps);
1654 jalview.bin.Cache.log.debug("reusing DseqFor ID");
1657 mp.setMappingChoice(mpc);
1663 String SetUserColourScheme(jalview.schemes.ColourSchemeI cs,
1664 Vector userColours, JalviewModelSequence jms)
1667 jalview.schemes.UserColourScheme ucs = (jalview.schemes.UserColourScheme) cs;
1668 boolean newucs = false;
1669 if (!userColours.contains(ucs))
1671 userColours.add(ucs);
1674 id = "ucs" + userColours.indexOf(ucs);
1677 // actually create the scheme's entry in the XML model
1678 java.awt.Color[] colours = ucs.getColours();
1679 jalview.schemabinding.version2.UserColours uc = new jalview.schemabinding.version2.UserColours();
1680 jalview.schemabinding.version2.UserColourScheme jbucs = new jalview.schemabinding.version2.UserColourScheme();
1682 for (int i = 0; i < colours.length; i++)
1684 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
1685 col.setName(ResidueProperties.aa[i]);
1686 col.setRGB(jalview.util.Format.getHexString(colours[i]));
1687 jbucs.addColour(col);
1689 if (ucs.getLowerCaseColours() != null)
1691 colours = ucs.getLowerCaseColours();
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].toLowerCase());
1696 col.setRGB(jalview.util.Format.getHexString(colours[i]));
1697 jbucs.addColour(col);
1702 uc.setUserColourScheme(jbucs);
1703 jms.addUserColours(uc);
1709 jalview.schemes.UserColourScheme GetUserColourScheme(
1710 JalviewModelSequence jms, String id)
1712 UserColours[] uc = jms.getUserColours();
1713 UserColours colours = null;
1715 for (int i = 0; i < uc.length; i++)
1717 if (uc[i].getId().equals(id))
1725 java.awt.Color[] newColours = new java.awt.Color[24];
1727 for (int i = 0; i < 24; i++)
1729 newColours[i] = new java.awt.Color(Integer.parseInt(colours
1730 .getUserColourScheme().getColour(i).getRGB(), 16));
1733 jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme(
1736 if (colours.getUserColourScheme().getColourCount() > 24)
1738 newColours = new java.awt.Color[23];
1739 for (int i = 0; i < 23; i++)
1741 newColours[i] = new java.awt.Color(Integer.parseInt(colours
1742 .getUserColourScheme().getColour(i + 24).getRGB(), 16));
1744 ucs.setLowerCaseColours(newColours);
1751 * contains last error message (if any) encountered by XML loader.
1753 String errorMessage = null;
1756 * flag to control whether the Jalview2XML_V1 parser should be deferred to if
1757 * exceptions are raised during project XML parsing
1759 public boolean attemptversion1parse = true;
1762 * Load a jalview project archive from a jar file
1765 * - HTTP URL or filename
1767 public AlignFrame LoadJalviewAlign(final String file)
1770 jalview.gui.AlignFrame af = null;
1774 // create list to store references for any new Jmol viewers created
1775 newStructureViewers=new Vector<AppJmol>();
1776 // UNMARSHALLER SEEMS TO CLOSE JARINPUTSTREAM, MOST ANNOYING
1777 // Workaround is to make sure caller implements the JarInputStreamProvider
1779 // so we can re-open the jar input stream for each entry.
1781 jarInputStreamProvider jprovider = createjarInputStreamProvider(file);
1782 af = LoadJalviewAlign(jprovider);
1784 } catch (MalformedURLException e)
1786 errorMessage = "Invalid URL format for '" + file + "'";
1792 SwingUtilities.invokeAndWait(new Runnable()
1796 setLoadingFinishedForNewStructureViewers();
1799 } catch (Exception x)
1807 private jarInputStreamProvider createjarInputStreamProvider(
1808 final String file) throws MalformedURLException
1811 errorMessage = null;
1812 uniqueSetSuffix = null;
1814 viewportsAdded = null;
1815 frefedSequence = null;
1817 if (file.startsWith("http://"))
1819 url = new URL(file);
1821 final URL _url = url;
1822 return new jarInputStreamProvider()
1826 public JarInputStream getJarInputStream() throws IOException
1830 return new JarInputStream(_url.openStream());
1834 return new JarInputStream(new FileInputStream(file));
1839 public String getFilename()
1847 * Recover jalview session from a jalview project archive. Caller may
1848 * initialise uniqueSetSuffix, seqRefIds, viewportsAdded and frefedSequence
1849 * themselves. Any null fields will be initialised with default values,
1850 * non-null fields are left alone.
1855 public AlignFrame LoadJalviewAlign(final jarInputStreamProvider jprovider)
1857 errorMessage = null;
1858 if (uniqueSetSuffix == null)
1860 uniqueSetSuffix = System.currentTimeMillis() % 100000 + "";
1862 if (seqRefIds == null)
1864 seqRefIds = new Hashtable();
1866 if (viewportsAdded == null)
1868 viewportsAdded = new Hashtable();
1870 if (frefedSequence == null)
1872 frefedSequence = new Vector();
1875 jalview.gui.AlignFrame af= null,_af = null;
1876 Hashtable gatherToThisFrame = new Hashtable();
1877 final String file = jprovider.getFilename();
1880 JarInputStream jin = null;
1881 JarEntry jarentry = null;
1886 jin = jprovider.getJarInputStream();
1887 for (int i = 0; i < entryCount; i++)
1889 jarentry = jin.getNextJarEntry();
1892 if (jarentry != null && jarentry.getName().endsWith(".xml"))
1894 InputStreamReader in = new InputStreamReader(jin, "UTF-8");
1895 JalviewModel object = new JalviewModel();
1897 Unmarshaller unmar = new Unmarshaller(object);
1898 unmar.setValidation(false);
1899 object = (JalviewModel) unmar.unmarshal(in);
1900 if (true) // !skipViewport(object))
1902 _af = LoadFromObject(object, file, true, jprovider);
1903 if (object.getJalviewModelSequence().getViewportCount() > 0)
1906 if (object.getJalviewModelSequence().getViewportCount() > 1
1907 && af.viewport.gatherViewsHere)
1909 gatherToThisFrame.put(af.viewport.getSequenceSetId(), af);
1915 else if (jarentry != null)
1917 // Some other file here.
1920 } while (jarentry != null);
1921 resolveFrefedSequences();
1922 } catch (java.io.FileNotFoundException ex)
1924 ex.printStackTrace();
1925 errorMessage = "Couldn't locate Jalview XML file : " + file;
1926 System.err.println("Exception whilst loading jalview XML file : "
1928 } catch (java.net.UnknownHostException ex)
1930 ex.printStackTrace();
1931 errorMessage = "Couldn't locate Jalview XML file : " + file;
1932 System.err.println("Exception whilst loading jalview XML file : "
1934 } catch (Exception ex)
1936 System.err.println("Parsing as Jalview Version 2 file failed.");
1937 ex.printStackTrace(System.err);
1938 if (attemptversion1parse)
1940 // Is Version 1 Jar file?
1943 af = new Jalview2XML_V1(raiseGUI).LoadJalviewAlign(jprovider);
1944 } catch (Exception ex2)
1946 System.err.println("Exception whilst loading as jalviewXMLV1:");
1947 ex2.printStackTrace();
1951 if (Desktop.instance != null)
1953 Desktop.instance.stopLoading();
1957 System.out.println("Successfully loaded archive file");
1960 ex.printStackTrace();
1962 System.err.println("Exception whilst loading jalview XML file : "
1964 } catch (OutOfMemoryError e)
1966 // Don't use the OOM Window here
1967 errorMessage = "Out of memory loading jalview XML file";
1968 System.err.println("Out of memory whilst loading jalview XML file");
1969 e.printStackTrace();
1972 if (Desktop.instance != null)
1974 Desktop.instance.stopLoading();
1977 Enumeration en = gatherToThisFrame.elements();
1978 while (en.hasMoreElements())
1980 Desktop.instance.gatherViews((AlignFrame) en.nextElement());
1982 if (errorMessage != null)
1990 * check errorMessage for a valid error message and raise an error box in the
1991 * GUI or write the current errorMessage to stderr and then clear the error
1994 protected void reportErrors()
1996 reportErrors(false);
1999 protected void reportErrors(final boolean saving)
2001 if (errorMessage != null)
2003 final String finalErrorMessage = errorMessage;
2006 javax.swing.SwingUtilities.invokeLater(new Runnable()
2011 JOptionPane.showInternalMessageDialog(Desktop.desktop,
2012 finalErrorMessage, "Error "
2013 + (saving ? "saving" : "loading")
2014 + " Jalview file", JOptionPane.WARNING_MESSAGE);
2020 System.err.println("Problem loading Jalview file: " + errorMessage);
2023 errorMessage = null;
2026 Hashtable alreadyLoadedPDB;
2029 * when set, local views will be updated from view stored in JalviewXML
2030 * Currently (28th Sep 2008) things will go horribly wrong in vamsas document
2031 * sync if this is set to true.
2033 private final boolean updateLocalViews = false;
2035 String loadPDBFile(jarInputStreamProvider jprovider, String pdbId)
2037 if (alreadyLoadedPDB == null)
2038 alreadyLoadedPDB = new Hashtable();
2040 if (alreadyLoadedPDB.containsKey(pdbId))
2041 return alreadyLoadedPDB.get(pdbId).toString();
2045 JarInputStream jin = jprovider.getJarInputStream();
2047 * if (jprovider.startsWith("http://")) { jin = new JarInputStream(new
2048 * URL(jprovider).openStream()); } else { jin = new JarInputStream(new
2049 * FileInputStream(jprovider)); }
2052 JarEntry entry = null;
2055 entry = jin.getNextJarEntry();
2056 } while (entry != null && !entry.getName().equals(pdbId));
2059 BufferedReader in = new BufferedReader(new InputStreamReader(jin));
2060 File outFile = File.createTempFile("jalview_pdb", ".txt");
2061 outFile.deleteOnExit();
2062 PrintWriter out = new PrintWriter(new FileOutputStream(outFile));
2065 while ((data = in.readLine()) != null)
2072 } catch (Exception foo)
2077 String t = outFile.getAbsolutePath();
2078 alreadyLoadedPDB.put(pdbId, t);
2083 warn("Couldn't find PDB file entry in Jalview Jar for " + pdbId);
2085 } catch (Exception ex)
2087 ex.printStackTrace();
2093 private class JvAnnotRow
2095 public JvAnnotRow(int i, AlignmentAnnotation jaa)
2102 * persisted version of annotation row from which to take vis properties
2104 public jalview.datamodel.AlignmentAnnotation template;
2107 * original position of the annotation row in the alignment
2113 * Load alignment frame from jalview XML DOM object
2118 * filename source string
2119 * @param loadTreesAndStructures
2120 * when false only create Viewport
2122 * data source provider
2123 * @return alignment frame created from view stored in DOM
2125 AlignFrame LoadFromObject(JalviewModel object, String file,
2126 boolean loadTreesAndStructures, jarInputStreamProvider jprovider)
2128 SequenceSet vamsasSet = object.getVamsasModel().getSequenceSet(0);
2129 Sequence[] vamsasSeq = vamsasSet.getSequence();
2131 JalviewModelSequence jms = object.getJalviewModelSequence();
2133 Viewport view = (jms.getViewportCount()>0) ? jms.getViewport(0) : null;
2135 // ////////////////////////////////
2138 Vector hiddenSeqs = null;
2139 jalview.datamodel.Sequence jseq;
2141 ArrayList tmpseqs = new ArrayList();
2143 boolean multipleView = false;
2145 JSeq[] JSEQ = object.getJalviewModelSequence().getJSeq();
2146 int vi = 0; // counter in vamsasSeq array
2147 for (int i = 0; i < JSEQ.length; i++)
2149 String seqId = JSEQ[i].getId();
2151 if (seqRefIds.get(seqId) != null)
2153 tmpseqs.add(seqRefIds.get(seqId));
2154 multipleView = true;
2158 jseq = new jalview.datamodel.Sequence(vamsasSeq[vi].getName(),
2159 vamsasSeq[vi].getSequence());
2160 jseq.setDescription(vamsasSeq[vi].getDescription());
2161 jseq.setStart(JSEQ[i].getStart());
2162 jseq.setEnd(JSEQ[i].getEnd());
2163 jseq.setVamsasId(uniqueSetSuffix + seqId);
2164 seqRefIds.put(vamsasSeq[vi].getId(), jseq);
2169 if (JSEQ[i].getHidden())
2171 if (hiddenSeqs == null)
2173 hiddenSeqs = new Vector();
2176 hiddenSeqs.addElement(seqRefIds.get(seqId));
2182 // Create the alignment object from the sequence set
2183 // ///////////////////////////////
2184 jalview.datamodel.Sequence[] orderedSeqs = new jalview.datamodel.Sequence[tmpseqs
2187 tmpseqs.toArray(orderedSeqs);
2189 jalview.datamodel.Alignment al = new jalview.datamodel.Alignment(
2192 // / Add the alignment properties
2193 for (int i = 0; i < vamsasSet.getSequenceSetPropertiesCount(); i++)
2195 SequenceSetProperties ssp = vamsasSet.getSequenceSetProperties(i);
2196 al.setProperty(ssp.getKey(), ssp.getValue());
2200 // SequenceFeatures are added to the DatasetSequence,
2201 // so we must create or recover the dataset before loading features
2202 // ///////////////////////////////
2203 if (vamsasSet.getDatasetId() == null || vamsasSet.getDatasetId() == "")
2205 // older jalview projects do not have a dataset id.
2206 al.setDataset(null);
2210 recoverDatasetFor(vamsasSet, al);
2212 // ///////////////////////////////
2214 Hashtable pdbloaded = new Hashtable();
2217 // load sequence features, database references and any associated PDB
2218 // structures for the alignment
2219 for (int i = 0; i < vamsasSeq.length; i++)
2221 if (JSEQ[i].getFeaturesCount() > 0)
2223 Features[] features = JSEQ[i].getFeatures();
2224 for (int f = 0; f < features.length; f++)
2226 jalview.datamodel.SequenceFeature sf = new jalview.datamodel.SequenceFeature(
2227 features[f].getType(), features[f].getDescription(),
2228 features[f].getStatus(), features[f].getBegin(),
2229 features[f].getEnd(), features[f].getFeatureGroup());
2231 sf.setScore(features[f].getScore());
2232 for (int od = 0; od < features[f].getOtherDataCount(); od++)
2234 OtherData keyValue = features[f].getOtherData(od);
2235 if (keyValue.getKey().startsWith("LINK"))
2237 sf.addLink(keyValue.getValue());
2241 sf.setValue(keyValue.getKey(), keyValue.getValue());
2246 al.getSequenceAt(i).getDatasetSequence().addSequenceFeature(sf);
2249 if (vamsasSeq[i].getDBRefCount() > 0)
2251 addDBRefs(al.getSequenceAt(i).getDatasetSequence(), vamsasSeq[i]);
2253 if (JSEQ[i].getPdbidsCount() > 0)
2255 Pdbids[] ids = JSEQ[i].getPdbids();
2256 for (int p = 0; p < ids.length; p++)
2258 jalview.datamodel.PDBEntry entry = new jalview.datamodel.PDBEntry();
2259 entry.setId(ids[p].getId());
2260 entry.setType(ids[p].getType());
2261 if (ids[p].getFile() != null)
2263 if (!pdbloaded.containsKey(ids[p].getFile()))
2265 entry.setFile(loadPDBFile(jprovider, ids[p].getId()));
2269 entry.setFile(pdbloaded.get(ids[p].getId()).toString());
2273 al.getSequenceAt(i).getDatasetSequence().addPDBId(entry);
2277 } // end !multipleview
2279 // ///////////////////////////////
2280 // LOAD SEQUENCE MAPPINGS
2282 if (vamsasSet.getAlcodonFrameCount() > 0)
2284 // TODO Potentially this should only be done once for all views of an
2286 AlcodonFrame[] alc = vamsasSet.getAlcodonFrame();
2287 for (int i = 0; i < alc.length; i++)
2289 jalview.datamodel.AlignedCodonFrame cf = new jalview.datamodel.AlignedCodonFrame(
2290 alc[i].getAlcodonCount());
2291 if (alc[i].getAlcodonCount() > 0)
2293 Alcodon[] alcods = alc[i].getAlcodon();
2294 for (int p = 0; p < cf.codons.length; p++)
2296 if (alcods[p].hasPos1() && alcods[p].hasPos2()
2297 && alcods[p].hasPos3())
2299 // translated codons require three valid positions
2300 cf.codons[p] = new int[3];
2301 cf.codons[p][0] = (int) alcods[p].getPos1();
2302 cf.codons[p][1] = (int) alcods[p].getPos2();
2303 cf.codons[p][2] = (int) alcods[p].getPos3();
2307 cf.codons[p] = null;
2311 if (alc[i].getAlcodMapCount() > 0)
2313 AlcodMap[] maps = alc[i].getAlcodMap();
2314 for (int m = 0; m < maps.length; m++)
2316 SequenceI dnaseq = (SequenceI) seqRefIds
2317 .get(maps[m].getDnasq());
2319 jalview.datamodel.Mapping mapping = null;
2320 // attach to dna sequence reference.
2321 if (maps[m].getMapping() != null)
2323 mapping = addMapping(maps[m].getMapping());
2327 cf.addMap(dnaseq, mapping.getTo(), mapping.getMap());
2332 frefedSequence.add(new Object[]
2333 { maps[m].getDnasq(), cf, mapping });
2337 al.addCodonFrame(cf);
2342 // ////////////////////////////////
2344 ArrayList<JvAnnotRow> autoAlan = new ArrayList<JvAnnotRow>();
2346 * store any annotations which forward reference a group's ID
2348 Hashtable<String, ArrayList<jalview.datamodel.AlignmentAnnotation>> groupAnnotRefs = new Hashtable<String, ArrayList<jalview.datamodel.AlignmentAnnotation>>();
2350 if (vamsasSet.getAnnotationCount() > 0)
2352 Annotation[] an = vamsasSet.getAnnotation();
2354 for (int i = 0; i < an.length; i++)
2357 * test if annotation is automatically calculated for this view only
2359 boolean autoForView = false;
2360 if (an[i].getLabel().equals("Quality")
2361 || an[i].getLabel().equals("Conservation")
2362 || an[i].getLabel().equals("Consensus"))
2364 // Kludge for pre 2.5 projects which lacked the autocalculated flag
2366 if (!an[i].hasAutoCalculated())
2368 an[i].setAutoCalculated(true);
2372 || (an[i].hasAutoCalculated() && an[i].isAutoCalculated()))
2374 // remove ID - we don't recover annotation from other views for
2375 // view-specific annotation
2379 // set visiblity for other annotation in this view
2380 if (an[i].getId() != null
2381 && annotationIds.containsKey(an[i].getId()))
2383 jalview.datamodel.AlignmentAnnotation jda = (jalview.datamodel.AlignmentAnnotation) annotationIds
2384 .get(an[i].getId());
2385 // in principle Visible should always be true for annotation displayed
2386 // in multiple views
2387 if (an[i].hasVisible())
2388 jda.visible = an[i].getVisible();
2390 al.addAnnotation(jda);
2394 // Construct new annotation from model.
2395 AnnotationElement[] ae = an[i].getAnnotationElement();
2396 jalview.datamodel.Annotation[] anot = null;
2397 java.awt.Color firstColour = null;
2399 if (!an[i].getScoreOnly())
2401 anot = new jalview.datamodel.Annotation[al.getWidth()];
2402 for (int aa = 0; aa < ae.length && aa < anot.length; aa++)
2404 anpos = ae[aa].getPosition();
2406 if (anpos >= anot.length)
2409 anot[anpos] = new jalview.datamodel.Annotation(
2411 ae[aa].getDisplayCharacter(), ae[aa].getDescription(),
2412 (ae[aa].getSecondaryStructure() == null || ae[aa]
2413 .getSecondaryStructure().length() == 0) ? ' '
2414 : ae[aa].getSecondaryStructure().charAt(0),
2418 // JBPNote: Consider verifying dataflow for IO of secondary
2419 // structure annotation read from Stockholm files
2420 // this was added to try to ensure that
2421 // if (anot[ae[aa].getPosition()].secondaryStructure>' ')
2423 // anot[ae[aa].getPosition()].displayCharacter = "";
2425 anot[anpos].colour = new java.awt.Color(ae[aa].getColour());
2426 if (firstColour == null)
2428 firstColour = anot[anpos].colour;
2432 jalview.datamodel.AlignmentAnnotation jaa = null;
2434 if (an[i].getGraph())
2436 float llim = 0, hlim = 0;
2437 // if (autoForView || an[i].isAutoCalculated()) {
2440 jaa = new jalview.datamodel.AlignmentAnnotation(an[i].getLabel(),
2441 an[i].getDescription(), anot, llim, hlim,
2442 an[i].getGraphType());
2444 jaa.graphGroup = an[i].getGraphGroup();
2445 jaa._linecolour = firstColour;
2446 if (an[i].getThresholdLine() != null)
2448 jaa.setThreshold(new jalview.datamodel.GraphLine(an[i]
2449 .getThresholdLine().getValue(), an[i]
2450 .getThresholdLine().getLabel(), new java.awt.Color(
2451 an[i].getThresholdLine().getColour())));
2454 if (autoForView || an[i].isAutoCalculated())
2456 // Hardwire the symbol display line to ensure that labels for
2457 // histograms are displayed
2463 jaa = new jalview.datamodel.AlignmentAnnotation(an[i].getLabel(),
2464 an[i].getDescription(), anot);
2465 jaa._linecolour = firstColour;
2467 // register new annotation
2468 if (an[i].getId() != null)
2470 annotationIds.put(an[i].getId(), jaa);
2471 jaa.annotationId = an[i].getId();
2473 // recover sequence association
2474 if (an[i].getSequenceRef() != null)
2476 if (al.findName(an[i].getSequenceRef()) != null)
2478 jaa.createSequenceMapping(al.findName(an[i].getSequenceRef()),
2480 al.findName(an[i].getSequenceRef()).addAlignmentAnnotation(jaa);
2483 // and make a note of any group association
2484 if (an[i].getGroupRef() != null && an[i].getGroupRef().length() > 0)
2486 ArrayList<jalview.datamodel.AlignmentAnnotation> aal = groupAnnotRefs
2487 .get(an[i].getGroupRef());
2490 aal = new ArrayList<jalview.datamodel.AlignmentAnnotation>();
2491 groupAnnotRefs.put(an[i].getGroupRef(), aal);
2496 if (an[i].hasScore())
2498 jaa.setScore(an[i].getScore());
2500 if (an[i].hasVisible())
2501 jaa.visible = an[i].getVisible();
2503 if (an[i].hasCentreColLabels())
2504 jaa.centreColLabels = an[i].getCentreColLabels();
2506 if (an[i].hasScaleColLabels())
2508 jaa.scaleColLabel = an[i].getScaleColLabels();
2510 if (an[i].hasAutoCalculated() && an[i].isAutoCalculated())
2512 // newer files have an 'autoCalculated' flag and store calculation
2513 // state in viewport properties
2514 jaa.autoCalculated = true; // means annotation will be marked for
2515 // update at end of load.
2517 if (an[i].hasGraphHeight())
2519 jaa.graphHeight = an[i].getGraphHeight();
2521 if (an[i].hasBelowAlignment())
2523 jaa.belowAlignment = an[i].isBelowAlignment();
2525 jaa.setCalcId(an[i].getCalcId());
2527 if (jaa.autoCalculated)
2529 autoAlan.add(new JvAnnotRow(i, jaa));
2532 // if (!autoForView)
2534 // add autocalculated group annotation and any user created annotation
2536 al.addAnnotation(jaa);
2541 // ///////////////////////
2543 // Create alignment markup and styles for this view
2544 if (jms.getJGroupCount() > 0)
2546 JGroup[] groups = jms.getJGroup();
2548 for (int i = 0; i < groups.length; i++)
2550 ColourSchemeI cs = null;
2552 if (groups[i].getColour() != null)
2554 if (groups[i].getColour().startsWith("ucs"))
2556 cs = GetUserColourScheme(jms, groups[i].getColour());
2560 cs = ColourSchemeProperty.getColour(al, groups[i].getColour());
2565 cs.setThreshold(groups[i].getPidThreshold(), true);
2569 Vector seqs = new Vector();
2571 for (int s = 0; s < groups[i].getSeqCount(); s++)
2573 String seqId = groups[i].getSeq(s) + "";
2574 jalview.datamodel.SequenceI ts = (jalview.datamodel.SequenceI) seqRefIds
2579 seqs.addElement(ts);
2583 if (seqs.size() < 1)
2588 jalview.datamodel.SequenceGroup sg = new jalview.datamodel.SequenceGroup(
2589 seqs, groups[i].getName(), cs, groups[i].getDisplayBoxes(),
2590 groups[i].getDisplayText(), groups[i].getColourText(),
2591 groups[i].getStart(), groups[i].getEnd());
2593 sg.setOutlineColour(new java.awt.Color(groups[i].getOutlineColour()));
2595 sg.textColour = new java.awt.Color(groups[i].getTextCol1());
2596 sg.textColour2 = new java.awt.Color(groups[i].getTextCol2());
2597 sg.setShowNonconserved(groups[i].hasShowUnconserved() ? groups[i]
2598 .isShowUnconserved() : false);
2599 sg.thresholdTextColour = groups[i].getTextColThreshold();
2600 if (groups[i].hasShowConsensusHistogram())
2602 sg.setShowConsensusHistogram(groups[i].isShowConsensusHistogram());
2605 if (groups[i].hasShowSequenceLogo())
2607 sg.setshowSequenceLogo(groups[i].isShowSequenceLogo());
2609 if (groups[i].hasNormaliseSequenceLogo())
2611 sg.setNormaliseSequenceLogo(groups[i].isNormaliseSequenceLogo());
2613 if (groups[i].hasIgnoreGapsinConsensus())
2615 sg.setIgnoreGapsConsensus(groups[i].getIgnoreGapsinConsensus());
2617 if (groups[i].getConsThreshold() != 0)
2619 jalview.analysis.Conservation c = new jalview.analysis.Conservation(
2620 "All", ResidueProperties.propHash, 3,
2621 sg.getSequences(null), 0, sg.getWidth() - 1);
2623 c.verdict(false, 25);
2624 sg.cs.setConservation(c);
2627 if (groups[i].getId() != null && groupAnnotRefs.size() > 0)
2629 // re-instate unique group/annotation row reference
2630 ArrayList<jalview.datamodel.AlignmentAnnotation> jaal = groupAnnotRefs
2631 .get(groups[i].getId());
2634 for (jalview.datamodel.AlignmentAnnotation jaa : jaal)
2637 if (jaa.autoCalculated)
2639 // match up and try to set group autocalc alignment row for this
2641 if (jaa.label.startsWith("Consensus for "))
2643 sg.setConsensus(jaa);
2645 // match up and try to set group autocalc alignment row for this
2647 if (jaa.label.startsWith("Conservation for "))
2649 sg.setConservationRow(jaa);
2661 // only dataset in this model, so just return.
2664 // ///////////////////////////////
2667 // If we just load in the same jar file again, the sequenceSetId
2668 // will be the same, and we end up with multiple references
2669 // to the same sequenceSet. We must modify this id on load
2670 // so that each load of the file gives a unique id
2671 String uniqueSeqSetId = view.getSequenceSetId() + uniqueSetSuffix;
2672 String viewId = (view.getId() == null ? null : view.getId()
2674 AlignFrame af = null;
2675 AlignViewport av = null;
2676 // now check to see if we really need to create a new viewport.
2677 if (multipleView && viewportsAdded.size() == 0)
2679 // We recovered an alignment for which a viewport already exists.
2680 // TODO: fix up any settings necessary for overlaying stored state onto
2681 // state recovered from another document. (may not be necessary).
2682 // we may need a binding from a viewport in memory to one recovered from
2684 // and then recover its containing af to allow the settings to be applied.
2685 // TODO: fix for vamsas demo
2687 .println("About to recover a viewport for existing alignment: Sequence set ID is "
2689 Object seqsetobj = retrieveExistingObj(uniqueSeqSetId);
2690 if (seqsetobj != null)
2692 if (seqsetobj instanceof String)
2694 uniqueSeqSetId = (String) seqsetobj;
2696 .println("Recovered extant sequence set ID mapping for ID : New Sequence set ID is "
2702 .println("Warning : Collision between sequence set ID string and existing jalview object mapping.");
2707 AlignmentPanel ap = null;
2708 boolean isnewview = true;
2711 // Check to see if this alignment already has a view id == viewId
2712 jalview.gui.AlignmentPanel views[] = Desktop
2713 .getAlignmentPanels(uniqueSeqSetId);
2714 if (views != null && views.length > 0)
2716 for (int v = 0; v < views.length; v++)
2718 if (views[v].av.getViewId().equalsIgnoreCase(viewId))
2720 // recover the existing alignpanel, alignframe, viewport
2721 af = views[v].alignFrame;
2724 // TODO: could even skip resetting view settings if we don't want to
2725 // change the local settings from other jalview processes
2734 af = loadViewport(file, JSEQ, hiddenSeqs, al, jms, view,
2735 uniqueSeqSetId, viewId, autoAlan);
2740 // /////////////////////////////////////
2741 if (loadTreesAndStructures && jms.getTreeCount() > 0)
2745 for (int t = 0; t < jms.getTreeCount(); t++)
2748 Tree tree = jms.getTree(t);
2750 TreePanel tp = (TreePanel) retrieveExistingObj(tree.getId());
2753 tp = af.ShowNewickTree(
2754 new jalview.io.NewickFile(tree.getNewick()),
2755 tree.getTitle(), tree.getWidth(), tree.getHeight(),
2756 tree.getXpos(), tree.getYpos());
2757 if (tree.getId() != null)
2759 // perhaps bind the tree id to something ?
2764 // update local tree attributes ?
2765 // TODO: should check if tp has been manipulated by user - if so its
2766 // settings shouldn't be modified
2767 tp.setTitle(tree.getTitle());
2768 tp.setBounds(new Rectangle(tree.getXpos(), tree.getYpos(), tree
2769 .getWidth(), tree.getHeight()));
2770 tp.av = av; // af.viewport; // TODO: verify 'associate with all
2773 tp.treeCanvas.av = av; // af.viewport;
2774 tp.treeCanvas.ap = ap; // af.alignPanel;
2779 warn("There was a problem recovering stored Newick tree: \n"
2780 + tree.getNewick());
2784 tp.fitToWindow.setState(tree.getFitToWindow());
2785 tp.fitToWindow_actionPerformed(null);
2787 if (tree.getFontName() != null)
2789 tp.setTreeFont(new java.awt.Font(tree.getFontName(), tree
2790 .getFontStyle(), tree.getFontSize()));
2794 tp.setTreeFont(new java.awt.Font(view.getFontName(), view
2795 .getFontStyle(), tree.getFontSize()));
2798 tp.showPlaceholders(tree.getMarkUnlinked());
2799 tp.showBootstrap(tree.getShowBootstrap());
2800 tp.showDistances(tree.getShowDistances());
2802 tp.treeCanvas.threshold = tree.getThreshold();
2804 if (tree.getCurrentTree())
2806 af.viewport.setCurrentTree(tp.getTree());
2810 } catch (Exception ex)
2812 ex.printStackTrace();
2816 // //LOAD STRUCTURES
2817 if (loadTreesAndStructures)
2819 // run through all PDB ids on the alignment, and collect mappings between
2820 // jmol view ids and all sequences referring to it
2821 Hashtable<String, Object[]> jmolViewIds = new Hashtable();
2823 for (int i = 0; i < JSEQ.length; i++)
2825 if (JSEQ[i].getPdbidsCount() > 0)
2827 Pdbids[] ids = JSEQ[i].getPdbids();
2828 for (int p = 0; p < ids.length; p++)
2830 for (int s = 0; s < ids[p].getStructureStateCount(); s++)
2832 // check to see if we haven't already created this structure view
2833 String sviewid = (ids[p].getStructureState(s).getViewId() == null) ? null
2834 : ids[p].getStructureState(s).getViewId()
2836 jalview.datamodel.PDBEntry jpdb = new jalview.datamodel.PDBEntry();
2837 // Originally : ids[p].getFile()
2838 // : TODO: verify external PDB file recovery still works in normal
2839 // jalview project load
2840 jpdb.setFile(loadPDBFile(jprovider, ids[p].getId()));
2841 jpdb.setId(ids[p].getId());
2843 int x = ids[p].getStructureState(s).getXpos();
2844 int y = ids[p].getStructureState(s).getYpos();
2845 int width = ids[p].getStructureState(s).getWidth();
2846 int height = ids[p].getStructureState(s).getHeight();
2848 // Probably don't need to do this anymore...
2849 // Desktop.desktop.getComponentAt(x, y);
2850 // TODO: NOW: check that this recovers the PDB file correctly.
2851 String pdbFile = loadPDBFile(jprovider, ids[p].getId());
2852 jalview.datamodel.SequenceI seq = (jalview.datamodel.SequenceI) seqRefIds
2853 .get(JSEQ[i].getId() + "");
2854 if (sviewid == null)
2856 sviewid = "_jalview_pre2_4_" + x + "," + y + "," + width
2859 if (!jmolViewIds.containsKey(sviewid))
2861 jmolViewIds.put(sviewid, new Object[]
2863 { x, y, width, height }, "",
2864 new Hashtable<String, Object[]>(), new boolean[]
2865 { false, false, true } });
2866 // Legacy pre-2.7 conversion JAL-823 :
2867 // do not assume any view has to be linked for colour by
2871 // assemble String[] { pdb files }, String[] { id for each
2872 // file }, orig_fileloc, SequenceI[][] {{ seqs_file 1 }, {
2873 // seqs_file 2}, boolean[] {
2874 // linkAlignPanel,superposeWithAlignpanel}} from hash
2875 Object[] jmoldat = jmolViewIds.get(sviewid);
2876 ((boolean[]) jmoldat[3])[0] |= ids[p].getStructureState(s)
2877 .hasAlignwithAlignPanel() ? ids[p].getStructureState(
2878 s).getAlignwithAlignPanel() : false;
2879 // never colour by linked panel if not specified
2880 ((boolean[]) jmoldat[3])[1] |= ids[p].getStructureState(s)
2881 .hasColourwithAlignPanel() ? ids[p]
2882 .getStructureState(s).getColourwithAlignPanel()
2884 // default for pre-2.7 projects is that Jmol colouring is enabled
2885 ((boolean[]) jmoldat[3])[2] &= ids[p].getStructureState(s)
2886 .hasColourByJmol() ? ids[p].getStructureState(s)
2887 .getColourByJmol() : true;
2889 if (((String) jmoldat[1]).length() < ids[p]
2890 .getStructureState(s).getContent().length())
2893 jmoldat[1] = ids[p].getStructureState(s).getContent();
2896 if (ids[p].getFile() != null)
2898 File mapkey = new File(ids[p].getFile());
2899 Object[] seqstrmaps = (Object[]) ((Hashtable) jmoldat[2])
2901 if (seqstrmaps == null)
2903 ((Hashtable) jmoldat[2]).put(mapkey,
2904 seqstrmaps = new Object[]
2905 { pdbFile, ids[p].getId(), new Vector(),
2908 if (!((Vector) seqstrmaps[2]).contains(seq))
2910 ((Vector) seqstrmaps[2]).addElement(seq);
2911 // ((Vector)seqstrmaps[3]).addElement(n) :
2912 // in principle, chains
2913 // should be stored here : do we need to
2914 // TODO: store and recover seq/pdb_id :
2920 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");
2929 // Instantiate the associated Jmol views
2930 for (Entry<String, Object[]> entry : jmolViewIds.entrySet())
2932 String sviewid = entry.getKey();
2933 Object[] svattrib = entry.getValue();
2934 int[] geom = (int[]) svattrib[0];
2935 String state = (String) svattrib[1];
2936 Hashtable<File, Object[]> oldFiles = (Hashtable<File, Object[]>) svattrib[2];
2937 final boolean useinJmolsuperpos = ((boolean[]) svattrib[3])[0], usetoColourbyseq = ((boolean[]) svattrib[3])[1], jmolColouring = ((boolean[]) svattrib[3])[2];
2938 int x = geom[0], y = geom[1], width = geom[2], height = geom[3];
2939 // collate the pdbfile -> sequence mappings from this view
2940 Vector<String> pdbfilenames = new Vector<String>();
2941 Vector<SequenceI[]> seqmaps = new Vector<SequenceI[]>();
2942 Vector<String> pdbids = new Vector<String>();
2944 // Search to see if we've already created this Jmol view
2945 AppJmol comp = null;
2946 JInternalFrame[] frames = null;
2951 frames = Desktop.desktop.getAllFrames();
2952 } catch (ArrayIndexOutOfBoundsException e)
2954 // occasional No such child exceptions are thrown here...
2959 } catch (Exception f)
2964 } while (frames == null);
2965 // search for any Jmol windows already open from other
2966 // alignment views that exactly match the stored structure state
2967 for (int f = 0; comp == null && f < frames.length; f++)
2969 if (frames[f] instanceof AppJmol)
2972 && ((AppJmol) frames[f]).getViewId().equals(sviewid))
2974 // post jalview 2.4 schema includes structure view id
2975 comp = (AppJmol) frames[f];
2977 else if (frames[f].getX() == x && frames[f].getY() == y
2978 && frames[f].getHeight() == height
2979 && frames[f].getWidth() == width)
2981 comp = (AppJmol) frames[f];
2988 // create a new Jmol window.
2989 // First parse the Jmol state to translate filenames loaded into the
2990 // view, and record the order in which files are shown in the Jmol
2991 // view, so we can add the sequence mappings in same order.
2992 StringBuffer newFileLoc = null;
2993 int cp = 0, ncp, ecp;
2994 while ((ncp = state.indexOf("load ", cp)) > -1)
2996 if (newFileLoc == null)
2998 newFileLoc = new StringBuffer();
3002 // look for next filename in load statement
3003 newFileLoc.append(state.substring(cp,
3004 ncp = (state.indexOf("\"", ncp + 1) + 1)));
3005 String oldfilenam = state.substring(ncp,
3006 ecp = state.indexOf("\"", ncp));
3007 // recover the new mapping data for this old filename
3008 // have to normalize filename - since Jmol and jalview do
3010 // translation differently.
3011 Object[] filedat = oldFiles.get(new File(oldfilenam));
3012 newFileLoc.append(Platform
3013 .escapeString((String) filedat[0]));
3014 pdbfilenames.addElement((String) filedat[0]);
3015 pdbids.addElement((String) filedat[1]);
3016 seqmaps.addElement(((Vector<SequenceI>) filedat[2])
3017 .toArray(new SequenceI[0]));
3018 newFileLoc.append("\"");
3019 cp = ecp + 1; // advance beyond last \" and set cursor so we can
3020 // look for next file statement.
3021 } while ((ncp = state.indexOf("/*file*/", cp)) > -1);
3025 // just append rest of state
3026 newFileLoc.append(state.substring(cp));
3031 .print("Ignoring incomplete Jmol state for PDB ids: ");
3032 newFileLoc = new StringBuffer(state);
3033 newFileLoc.append("; load append ");
3034 for (File id : oldFiles.keySet())
3036 // add this and any other pdb files that should be present in
3038 Object[] filedat = oldFiles.get(id);
3040 newFileLoc.append(((String) filedat[0]));
3041 pdbfilenames.addElement((String) filedat[0]);
3042 pdbids.addElement((String) filedat[1]);
3043 seqmaps.addElement(((Vector<SequenceI>) filedat[2])
3044 .toArray(new SequenceI[0]));
3045 newFileLoc.append(" \"");
3046 newFileLoc.append((String) filedat[0]);
3047 newFileLoc.append("\"");
3050 newFileLoc.append(";");
3053 if (newFileLoc != null)
3055 int histbug = newFileLoc.indexOf("history = ");
3057 int diff = histbug == -1 ? -1 : newFileLoc.indexOf(";",
3059 String val = (diff == -1) ? null : newFileLoc.substring(
3061 if (val != null && val.length() >= 4)
3063 if (val.contains("e"))
3065 if (val.trim().equals("true"))
3073 newFileLoc.replace(histbug, diff, val);
3076 // TODO: assemble String[] { pdb files }, String[] { id for each
3077 // file }, orig_fileloc, SequenceI[][] {{ seqs_file 1 }, {
3078 // seqs_file 2}} from hash
3079 final String[] pdbf = pdbfilenames
3080 .toArray(new String[pdbfilenames.size()]), id = pdbids
3081 .toArray(new String[pdbids.size()]);
3082 final SequenceI[][] sq = seqmaps
3083 .toArray(new SequenceI[seqmaps.size()][]);
3084 final String fileloc = newFileLoc.toString(), vid = sviewid;
3085 final AlignFrame alf = af;
3086 final java.awt.Rectangle rect = new java.awt.Rectangle(x, y,
3090 javax.swing.SwingUtilities.invokeAndWait(new Runnable()
3095 AppJmol sview = null;
3098 sview = new AppJmol(pdbf, id, sq, alf.alignPanel,
3099 useinJmolsuperpos, usetoColourbyseq,
3100 jmolColouring, fileloc, rect, vid);
3101 addNewStructureViewer(sview);
3102 } catch (OutOfMemoryError ex)
3104 new OOMWarning("restoring structure view for PDB id "
3105 + id, (OutOfMemoryError) ex.getCause());
3106 if (sview != null && sview.isVisible())
3108 sview.closeViewer();
3109 sview.setVisible(false);
3115 } catch (InvocationTargetException ex)
3117 warn("Unexpected error when opening Jmol view.", ex);
3119 } catch (InterruptedException e)
3121 // e.printStackTrace();
3127 // if (comp != null)
3129 // NOTE: if the jalview project is part of a shared session then
3130 // view synchronization should/could be done here.
3132 // add mapping for sequences in this view to an already open Jmol
3134 for (File id : oldFiles.keySet())
3136 // add this and any other pdb files that should be present in the
3138 Object[] filedat = oldFiles.get(id);
3139 String pdbFile = (String) filedat[0];
3140 SequenceI[] seq = ((Vector<SequenceI>) filedat[2])
3141 .toArray(new SequenceI[0]);
3142 comp.jmb.ssm.setMapping(seq, null, pdbFile,
3143 jalview.io.AppletFormatAdapter.FILE);
3144 comp.jmb.addSequenceForStructFile(pdbFile, seq);
3146 // and add the AlignmentPanel's reference to the Jmol view
3147 comp.addAlignmentPanel(ap);
3148 if (useinJmolsuperpos)
3150 comp.useAlignmentPanelForSuperposition(ap);
3154 comp.excludeAlignmentPanelForSuperposition(ap);
3156 if (usetoColourbyseq)
3158 comp.useAlignmentPanelForColourbyseq(ap, !jmolColouring);
3162 comp.excludeAlignmentPanelForColourbyseq(ap);
3168 // and finally return.
3171 Vector<AppJmol> newStructureViewers=null;
3172 protected void addNewStructureViewer(AppJmol sview)
3174 if (newStructureViewers!=null)
3176 sview.jmb.setFinishedLoadingFromArchive(false);
3177 newStructureViewers.add(sview);
3180 protected void setLoadingFinishedForNewStructureViewers()
3182 if (newStructureViewers!=null)
3184 for (AppJmol sview:newStructureViewers)
3186 sview.jmb.setFinishedLoadingFromArchive(true);
3188 newStructureViewers.clear();
3189 newStructureViewers=null;
3193 AlignFrame loadViewport(String file, JSeq[] JSEQ, Vector hiddenSeqs,
3194 Alignment al, JalviewModelSequence jms, Viewport view,
3195 String uniqueSeqSetId, String viewId,
3196 ArrayList<JvAnnotRow> autoAlan)
3198 AlignFrame af = null;
3199 af = new AlignFrame(al, view.getWidth(), view.getHeight(),
3200 uniqueSeqSetId, viewId);
3202 af.setFileName(file, "Jalview");
3204 for (int i = 0; i < JSEQ.length; i++)
3206 af.viewport.setSequenceColour(af.viewport.getAlignment()
3207 .getSequenceAt(i), new java.awt.Color(JSEQ[i].getColour()));
3210 af.viewport.gatherViewsHere = view.getGatheredViews();
3212 if (view.getSequenceSetId() != null)
3214 jalview.gui.AlignViewport av = (jalview.gui.AlignViewport) viewportsAdded
3215 .get(uniqueSeqSetId);
3217 af.viewport.setSequenceSetId(uniqueSeqSetId);
3220 // propagate shared settings to this new view
3221 af.viewport.historyList = av.historyList;
3222 af.viewport.redoList = av.redoList;
3226 viewportsAdded.put(uniqueSeqSetId, af.viewport);
3228 // TODO: check if this method can be called repeatedly without
3229 // side-effects if alignpanel already registered.
3230 PaintRefresher.Register(af.alignPanel, uniqueSeqSetId);
3232 // apply Hidden regions to view.
3233 if (hiddenSeqs != null)
3235 for (int s = 0; s < JSEQ.length; s++)
3237 jalview.datamodel.SequenceGroup hidden = new jalview.datamodel.SequenceGroup();
3239 for (int r = 0; r < JSEQ[s].getHiddenSequencesCount(); r++)
3242 al.getSequenceAt(JSEQ[s].getHiddenSequences(r)), false);
3244 af.viewport.hideRepSequences(al.getSequenceAt(s), hidden);
3247 jalview.datamodel.SequenceI[] hseqs = new jalview.datamodel.SequenceI[hiddenSeqs
3250 for (int s = 0; s < hiddenSeqs.size(); s++)
3252 hseqs[s] = (jalview.datamodel.SequenceI) hiddenSeqs.elementAt(s);
3255 af.viewport.hideSequence(hseqs);
3258 // recover view properties and display parameters
3259 if (view.getViewName() != null)
3261 af.viewport.viewName = view.getViewName();
3262 af.setInitialTabVisible();
3264 af.setBounds(view.getXpos(), view.getYpos(), view.getWidth(),
3267 af.viewport.setShowAnnotation(view.getShowAnnotation());
3268 af.viewport.setAbovePIDThreshold(view.getPidSelected());
3270 af.viewport.setColourText(view.getShowColourText());
3272 af.viewport.setConservationSelected(view.getConservationSelected());
3273 af.viewport.setShowJVSuffix(view.getShowFullId());
3274 af.viewport.rightAlignIds = view.getRightAlignIds();
3275 af.viewport.setFont(new java.awt.Font(view.getFontName(), view
3276 .getFontStyle(), view.getFontSize()));
3277 af.alignPanel.fontChanged();
3278 af.viewport.setRenderGaps(view.getRenderGaps());
3279 af.viewport.setWrapAlignment(view.getWrapAlignment());
3280 af.alignPanel.setWrapAlignment(view.getWrapAlignment());
3281 af.viewport.setShowAnnotation(view.getShowAnnotation());
3282 af.alignPanel.setAnnotationVisible(view.getShowAnnotation());
3284 af.viewport.setShowBoxes(view.getShowBoxes());
3286 af.viewport.setShowText(view.getShowText());
3288 af.viewport.textColour = new java.awt.Color(view.getTextCol1());
3289 af.viewport.textColour2 = new java.awt.Color(view.getTextCol2());
3290 af.viewport.thresholdTextColour = view.getTextColThreshold();
3291 af.viewport.setShowUnconserved(view.hasShowUnconserved() ? view
3292 .isShowUnconserved() : false);
3293 af.viewport.setStartRes(view.getStartRes());
3294 af.viewport.setStartSeq(view.getStartSeq());
3296 ColourSchemeI cs = null;
3297 // apply colourschemes
3298 if (view.getBgColour() != null)
3300 if (view.getBgColour().startsWith("ucs"))
3302 cs = GetUserColourScheme(jms, view.getBgColour());
3304 else if (view.getBgColour().startsWith("Annotation"))
3306 // int find annotation
3307 if (af.viewport.getAlignment().getAlignmentAnnotation() != null)
3309 for (int i = 0; i < af.viewport.getAlignment()
3310 .getAlignmentAnnotation().length; i++)
3312 if (af.viewport.getAlignment().getAlignmentAnnotation()[i].label
3313 .equals(view.getAnnotationColours().getAnnotation()))
3315 if (af.viewport.getAlignment().getAlignmentAnnotation()[i]
3316 .getThreshold() == null)
3318 af.viewport.getAlignment().getAlignmentAnnotation()[i]
3319 .setThreshold(new jalview.datamodel.GraphLine(view
3320 .getAnnotationColours().getThreshold(),
3321 "Threshold", java.awt.Color.black)
3326 if (view.getAnnotationColours().getColourScheme()
3329 cs = new AnnotationColourGradient(af.viewport
3330 .getAlignment().getAlignmentAnnotation()[i],
3331 new java.awt.Color(view.getAnnotationColours()
3332 .getMinColour()), new java.awt.Color(view
3333 .getAnnotationColours().getMaxColour()),
3334 view.getAnnotationColours().getAboveThreshold());
3336 else if (view.getAnnotationColours().getColourScheme()
3339 cs = new AnnotationColourGradient(af.viewport
3340 .getAlignment().getAlignmentAnnotation()[i],
3341 GetUserColourScheme(jms, view
3342 .getAnnotationColours().getColourScheme()),
3343 view.getAnnotationColours().getAboveThreshold());
3347 cs = new AnnotationColourGradient(af.viewport
3348 .getAlignment().getAlignmentAnnotation()[i],
3349 ColourSchemeProperty.getColour(al, view
3350 .getAnnotationColours().getColourScheme()),
3351 view.getAnnotationColours().getAboveThreshold());
3353 if (view.getAnnotationColours().hasPerSequence())
3355 ((AnnotationColourGradient)cs).setSeqAssociated(view.getAnnotationColours().isPerSequence());
3357 if (view.getAnnotationColours().hasPredefinedColours())
3359 ((AnnotationColourGradient)cs).setPredefinedColours(view.getAnnotationColours().isPredefinedColours());
3361 // Also use these settings for all the groups
3362 if (al.getGroups() != null)
3364 for (int g = 0; g < al.getGroups().size(); g++)
3366 jalview.datamodel.SequenceGroup sg = al.getGroups()
3376 * (view.getAnnotationColours().getColourScheme().equals("None"
3377 * )) { sg.cs = new AnnotationColourGradient(
3378 * af.viewport.getAlignment().getAlignmentAnnotation()[i], new
3379 * java.awt.Color(view.getAnnotationColours().
3380 * getMinColour()), new
3381 * java.awt.Color(view.getAnnotationColours().
3383 * view.getAnnotationColours().getAboveThreshold()); } else
3386 sg.cs = new AnnotationColourGradient(af.viewport
3387 .getAlignment().getAlignmentAnnotation()[i],
3388 sg.cs, view.getAnnotationColours()
3389 .getAboveThreshold());
3390 if (cs instanceof AnnotationColourGradient)
3392 if (view.getAnnotationColours().hasPerSequence())
3394 ((AnnotationColourGradient)cs).setSeqAssociated(view.getAnnotationColours().isPerSequence());
3396 if (view.getAnnotationColours().hasPredefinedColours())
3398 ((AnnotationColourGradient)cs).setPredefinedColours(view.getAnnotationColours().isPredefinedColours());
3414 cs = ColourSchemeProperty.getColour(al, view.getBgColour());
3419 cs.setThreshold(view.getPidThreshold(), true);
3420 cs.setConsensus(af.viewport.getSequenceConsensusHash());
3424 af.viewport.setGlobalColourScheme(cs);
3425 af.viewport.setColourAppliesToAllGroups(false);
3427 if (view.getConservationSelected() && cs != null)
3429 cs.setConservationInc(view.getConsThreshold());
3432 af.changeColour(cs);
3434 af.viewport.setColourAppliesToAllGroups(true);
3436 if (view.getShowSequenceFeatures())
3438 af.viewport.showSequenceFeatures = true;
3440 if (view.hasCentreColumnLabels())
3442 af.viewport.setCentreColumnLabels(view.getCentreColumnLabels());
3444 if (view.hasIgnoreGapsinConsensus())
3446 af.viewport.setIgnoreGapsConsensus(view.getIgnoreGapsinConsensus(),
3449 if (view.hasFollowHighlight())
3451 af.viewport.followHighlight = view.getFollowHighlight();
3453 if (view.hasFollowSelection())
3455 af.viewport.followSelection = view.getFollowSelection();
3457 if (view.hasShowConsensusHistogram())
3459 af.viewport.setShowConsensusHistogram(view
3460 .getShowConsensusHistogram());
3464 af.viewport.setShowConsensusHistogram(true);
3466 if (view.hasShowSequenceLogo())
3468 af.viewport.setShowSequenceLogo(view.getShowSequenceLogo());
3472 af.viewport.setShowSequenceLogo(false);
3474 if (view.hasNormaliseSequenceLogo())
3476 af.viewport.setNormaliseSequenceLogo(view.getNormaliseSequenceLogo());
3478 if (view.hasShowDbRefTooltip())
3480 af.viewport.setShowDbRefs(view.getShowDbRefTooltip());
3482 if (view.hasShowNPfeatureTooltip())
3484 af.viewport.setShowNpFeats(view.hasShowNPfeatureTooltip());
3486 if (view.hasShowGroupConsensus())
3488 af.viewport.setShowGroupConsensus(view.getShowGroupConsensus());
3492 af.viewport.setShowGroupConsensus(false);
3494 if (view.hasShowGroupConservation())
3496 af.viewport.setShowGroupConservation(view.getShowGroupConservation());
3500 af.viewport.setShowGroupConservation(false);
3503 // recover featre settings
3504 if (jms.getFeatureSettings() != null)
3506 af.viewport.featuresDisplayed = new Hashtable();
3507 String[] renderOrder = new String[jms.getFeatureSettings()
3508 .getSettingCount()];
3509 for (int fs = 0; fs < jms.getFeatureSettings().getSettingCount(); fs++)
3511 Setting setting = jms.getFeatureSettings().getSetting(fs);
3512 if (setting.hasMincolour())
3514 GraduatedColor gc = setting.hasMin() ? new GraduatedColor(
3515 new java.awt.Color(setting.getMincolour()),
3516 new java.awt.Color(setting.getColour()),
3517 setting.getMin(), setting.getMax()) : new GraduatedColor(
3518 new java.awt.Color(setting.getMincolour()),
3519 new java.awt.Color(setting.getColour()), 0, 1);
3520 if (setting.hasThreshold())
3522 gc.setThresh(setting.getThreshold());
3523 gc.setThreshType(setting.getThreshstate());
3525 gc.setAutoScaled(true); // default
3526 if (setting.hasAutoScale())
3528 gc.setAutoScaled(setting.getAutoScale());
3530 if (setting.hasColourByLabel())
3532 gc.setColourByLabel(setting.getColourByLabel());
3534 // and put in the feature colour table.
3535 af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().setColour(
3536 setting.getType(), gc);
3540 af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().setColour(
3542 new java.awt.Color(setting.getColour()));
3544 renderOrder[fs] = setting.getType();
3545 if (setting.hasOrder())
3546 af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().setOrder(
3547 setting.getType(), setting.getOrder());
3549 af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().setOrder(
3551 fs / jms.getFeatureSettings().getSettingCount());
3552 if (setting.getDisplay())
3554 af.viewport.featuresDisplayed.put(setting.getType(), new Integer(
3555 setting.getColour()));
3558 af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().renderOrder = renderOrder;
3560 af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().featureGroups = fgtable = new Hashtable();
3561 for (int gs = 0; gs < jms.getFeatureSettings().getGroupCount(); gs++)
3563 Group grp = jms.getFeatureSettings().getGroup(gs);
3564 fgtable.put(grp.getName(), new Boolean(grp.getDisplay()));
3568 if (view.getHiddenColumnsCount() > 0)
3570 for (int c = 0; c < view.getHiddenColumnsCount(); c++)
3572 af.viewport.hideColumns(view.getHiddenColumns(c).getStart(), view
3573 .getHiddenColumns(c).getEnd() // +1
3577 if (view.getCalcIdParam() != null)
3579 for (CalcIdParam calcIdParam : view.getCalcIdParam())
3581 if (calcIdParam != null)
3583 if (recoverCalcIdParam(calcIdParam, af.viewport))
3588 warn("Couldn't recover parameters for "
3589 + calcIdParam.getCalcId());
3594 af.setMenusFromViewport(af.viewport);
3595 // TODO: we don't need to do this if the viewport is aready visible.
3596 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
3598 af.alignPanel.updateAnnotation(false, true); // recompute any autoannotation
3599 reorderAutoannotation(af, al, autoAlan);
3600 af.alignPanel.alignmentChanged();
3604 private void reorderAutoannotation(AlignFrame af, Alignment al,
3605 ArrayList<JvAnnotRow> autoAlan)
3607 // copy over visualization settings for autocalculated annotation in the
3609 if (al.getAlignmentAnnotation() != null)
3612 * Kludge for magic autoannotation names (see JAL-811)
3614 String[] magicNames = new String[]
3615 { "Consensus", "Quality", "Conservation" };
3616 JvAnnotRow nullAnnot = new JvAnnotRow(-1, null);
3617 Hashtable<String, JvAnnotRow> visan = new Hashtable<String, JvAnnotRow>();
3618 for (String nm : magicNames)
3620 visan.put(nm, nullAnnot);
3622 for (JvAnnotRow auan : autoAlan)
3624 visan.put(auan.template.label
3625 + (auan.template.getCalcId() == null ? "" : "\t"
3626 + auan.template.getCalcId()), auan);
3628 int hSize = al.getAlignmentAnnotation().length;
3629 ArrayList<JvAnnotRow> reorder = new ArrayList<JvAnnotRow>();
3630 // work through any autoCalculated annotation already on the view
3631 // removing it if it should be placed in a different location on the
3632 // annotation panel.
3633 List<String> remains = new ArrayList(visan.keySet());
3634 for (int h = 0; h < hSize; h++)
3636 jalview.datamodel.AlignmentAnnotation jalan = al
3637 .getAlignmentAnnotation()[h];
3638 if (jalan.autoCalculated)
3641 JvAnnotRow valan = visan.get(k = jalan.label);
3642 if (jalan.getCalcId() != null)
3644 valan = visan.get(k = jalan.label + "\t" + jalan.getCalcId());
3649 // delete the auto calculated row from the alignment
3650 al.deleteAnnotation(jalan, false);
3654 if (valan != nullAnnot)
3656 if (jalan != valan.template)
3658 // newly created autoannotation row instance
3659 // so keep a reference to the visible annotation row
3660 // and copy over all relevant attributes
3661 if (valan.template.graphHeight >= 0)
3664 jalan.graphHeight = valan.template.graphHeight;
3666 jalan.visible = valan.template.visible;
3668 reorder.add(new JvAnnotRow(valan.order, jalan));
3673 // Add any (possibly stale) autocalculated rows that were not appended to
3674 // the view during construction
3675 for (String other : remains)
3677 JvAnnotRow othera = visan.get(other);
3678 if (othera != nullAnnot && othera.template.getCalcId() != null
3679 && othera.template.getCalcId().length() > 0)
3681 reorder.add(othera);
3684 // now put the automatic annotation in its correct place
3685 int s = 0, srt[] = new int[reorder.size()];
3686 JvAnnotRow[] rws = new JvAnnotRow[reorder.size()];
3687 for (JvAnnotRow jvar : reorder)
3690 srt[s++] = jvar.order;
3693 jalview.util.QuickSort.sort(srt, rws);
3694 // and re-insert the annotation at its correct position
3695 for (JvAnnotRow jvar : rws)
3697 al.addAnnotation(jvar.template, jvar.order);
3699 af.alignPanel.adjustAnnotationHeight();
3703 Hashtable skipList = null;
3706 * TODO remove this method
3709 * @return AlignFrame bound to sequenceSetId from view, if one exists. private
3710 * AlignFrame getSkippedFrame(Viewport view) { if (skipList==null) {
3711 * throw new Error("Implementation Error. No skipList defined for this
3712 * Jalview2XML instance."); } return (AlignFrame)
3713 * skipList.get(view.getSequenceSetId()); }
3717 * Check if the Jalview view contained in object should be skipped or not.
3720 * @return true if view's sequenceSetId is a key in skipList
3722 private boolean skipViewport(JalviewModel object)
3724 if (skipList == null)
3729 if (skipList.containsKey(id = object.getJalviewModelSequence()
3730 .getViewport()[0].getSequenceSetId()))
3732 if (Cache.log != null && Cache.log.isDebugEnabled())
3734 Cache.log.debug("Skipping seuqence set id " + id);
3741 public void AddToSkipList(AlignFrame af)
3743 if (skipList == null)
3745 skipList = new Hashtable();
3747 skipList.put(af.getViewport().getSequenceSetId(), af);
3750 public void clearSkipList()
3752 if (skipList != null)
3759 private void recoverDatasetFor(SequenceSet vamsasSet, Alignment al)
3761 jalview.datamodel.Alignment ds = getDatasetFor(vamsasSet.getDatasetId());
3762 Vector dseqs = null;
3765 // create a list of new dataset sequences
3766 dseqs = new Vector();
3768 for (int i = 0, iSize = vamsasSet.getSequenceCount(); i < iSize; i++)
3770 Sequence vamsasSeq = vamsasSet.getSequence(i);
3771 ensureJalviewDatasetSequence(vamsasSeq, ds, dseqs);
3773 // create a new dataset
3776 SequenceI[] dsseqs = new SequenceI[dseqs.size()];
3777 dseqs.copyInto(dsseqs);
3778 ds = new jalview.datamodel.Alignment(dsseqs);
3779 debug("Created new dataset " + vamsasSet.getDatasetId()
3780 + " for alignment " + System.identityHashCode(al));
3781 addDatasetRef(vamsasSet.getDatasetId(), ds);
3783 // set the dataset for the newly imported alignment.
3784 if (al.getDataset() == null)
3793 * sequence definition to create/merge dataset sequence for
3797 * vector to add new dataset sequence to
3799 private void ensureJalviewDatasetSequence(Sequence vamsasSeq,
3800 AlignmentI ds, Vector dseqs)
3802 // JBP TODO: Check this is called for AlCodonFrames to support recovery of
3804 jalview.datamodel.Sequence sq = (jalview.datamodel.Sequence) seqRefIds
3805 .get(vamsasSeq.getId());
3806 jalview.datamodel.SequenceI dsq = null;
3807 if (sq != null && sq.getDatasetSequence() != null)
3809 dsq = sq.getDatasetSequence();
3812 String sqid = vamsasSeq.getDsseqid();
3815 // need to create or add a new dataset sequence reference to this sequence
3818 dsq = (jalview.datamodel.SequenceI) seqRefIds.get(sqid);
3823 // make a new dataset sequence
3824 dsq = sq.createDatasetSequence();
3827 // make up a new dataset reference for this sequence
3828 sqid = seqHash(dsq);
3830 dsq.setVamsasId(uniqueSetSuffix + sqid);
3831 seqRefIds.put(sqid, dsq);
3836 dseqs.addElement(dsq);
3841 ds.addSequence(dsq);
3847 { // make this dataset sequence sq's dataset sequence
3848 sq.setDatasetSequence(dsq);
3849 // and update the current dataset alignment
3852 if (!dseqs.contains(dsq))
3857 if (ds.findIndex(dsq)<0)
3859 ds.addSequence(dsq);
3866 // TODO: refactor this as a merge dataset sequence function
3867 // now check that sq (the dataset sequence) sequence really is the union of
3868 // all references to it
3869 // boolean pre = sq.getStart() < dsq.getStart();
3870 // boolean post = sq.getEnd() > dsq.getEnd();
3874 StringBuffer sb = new StringBuffer();
3875 String newres = jalview.analysis.AlignSeq.extractGaps(
3876 jalview.util.Comparison.GapChars, sq.getSequenceAsString());
3877 if (!newres.equalsIgnoreCase(dsq.getSequenceAsString())
3878 && newres.length() > dsq.getLength())
3880 // Update with the longer sequence.
3884 * if (pre) { sb.insert(0, newres .substring(0, dsq.getStart() -
3885 * sq.getStart())); dsq.setStart(sq.getStart()); } if (post) {
3886 * sb.append(newres.substring(newres.length() - sq.getEnd() -
3887 * dsq.getEnd())); dsq.setEnd(sq.getEnd()); }
3889 dsq.setSequence(newres);
3891 // TODO: merges will never happen if we 'know' we have the real dataset
3892 // sequence - this should be detected when id==dssid
3893 System.err.println("DEBUG Notice: Merged dataset sequence (if you see this often, post at http://issues.jalview.org/browse/JAL-1474)"); // ("
3894 // + (pre ? "prepended" : "") + " "
3895 // + (post ? "appended" : ""));
3900 java.util.Hashtable datasetIds = null;
3902 java.util.IdentityHashMap dataset2Ids = null;
3904 private Alignment getDatasetFor(String datasetId)
3906 if (datasetIds == null)
3908 datasetIds = new Hashtable();
3911 if (datasetIds.containsKey(datasetId))
3913 return (Alignment) datasetIds.get(datasetId);
3918 private void addDatasetRef(String datasetId, Alignment dataset)
3920 if (datasetIds == null)
3922 datasetIds = new Hashtable();
3924 datasetIds.put(datasetId, dataset);
3928 * make a new dataset ID for this jalview dataset alignment
3933 private String getDatasetIdRef(jalview.datamodel.Alignment dataset)
3935 if (dataset.getDataset() != null)
3937 warn("Serious issue! Dataset Object passed to getDatasetIdRef is not a Jalview DATASET alignment...");
3939 String datasetId = makeHashCode(dataset, null);
3940 if (datasetId == null)
3942 // make a new datasetId and record it
3943 if (dataset2Ids == null)
3945 dataset2Ids = new IdentityHashMap();
3949 datasetId = (String) dataset2Ids.get(dataset);
3951 if (datasetId == null)
3953 datasetId = "ds" + dataset2Ids.size() + 1;
3954 dataset2Ids.put(dataset, datasetId);
3960 private void addDBRefs(SequenceI datasetSequence, Sequence sequence)
3962 for (int d = 0; d < sequence.getDBRefCount(); d++)
3964 DBRef dr = sequence.getDBRef(d);
3965 jalview.datamodel.DBRefEntry entry = new jalview.datamodel.DBRefEntry(
3966 sequence.getDBRef(d).getSource(), sequence.getDBRef(d)
3967 .getVersion(), sequence.getDBRef(d).getAccessionId());
3968 if (dr.getMapping() != null)
3970 entry.setMap(addMapping(dr.getMapping()));
3972 datasetSequence.addDBRef(entry);
3976 private jalview.datamodel.Mapping addMapping(Mapping m)
3978 SequenceI dsto = null;
3979 // Mapping m = dr.getMapping();
3980 int fr[] = new int[m.getMapListFromCount() * 2];
3981 Enumeration f = m.enumerateMapListFrom();
3982 for (int _i = 0; f.hasMoreElements(); _i += 2)
3984 MapListFrom mf = (MapListFrom) f.nextElement();
3985 fr[_i] = mf.getStart();
3986 fr[_i + 1] = mf.getEnd();
3988 int fto[] = new int[m.getMapListToCount() * 2];
3989 f = m.enumerateMapListTo();
3990 for (int _i = 0; f.hasMoreElements(); _i += 2)
3992 MapListTo mf = (MapListTo) f.nextElement();
3993 fto[_i] = mf.getStart();
3994 fto[_i + 1] = mf.getEnd();
3996 jalview.datamodel.Mapping jmap = new jalview.datamodel.Mapping(dsto,
3997 fr, fto, (int) m.getMapFromUnit(), (int) m.getMapToUnit());
3998 if (m.getMappingChoice() != null)
4000 MappingChoice mc = m.getMappingChoice();
4001 if (mc.getDseqFor() != null)
4003 String dsfor = "" + mc.getDseqFor();
4004 if (seqRefIds.containsKey(dsfor))
4009 jmap.setTo((SequenceI) seqRefIds.get(dsfor));
4013 frefedSequence.add(new Object[]
4020 * local sequence definition
4022 Sequence ms = mc.getSequence();
4023 jalview.datamodel.Sequence djs = null;
4024 String sqid = ms.getDsseqid();
4025 if (sqid != null && sqid.length() > 0)
4028 * recover dataset sequence
4030 djs = (jalview.datamodel.Sequence) seqRefIds.get(sqid);
4035 .println("Warning - making up dataset sequence id for DbRef sequence map reference");
4036 sqid = ((Object) ms).toString(); // make up a new hascode for
4037 // undefined dataset sequence hash
4038 // (unlikely to happen)
4044 * make a new dataset sequence and add it to refIds hash
4046 djs = new jalview.datamodel.Sequence(ms.getName(),
4048 djs.setStart(jmap.getMap().getToLowest());
4049 djs.setEnd(jmap.getMap().getToHighest());
4050 djs.setVamsasId(uniqueSetSuffix + sqid);
4052 seqRefIds.put(sqid, djs);
4055 jalview.bin.Cache.log.debug("about to recurse on addDBRefs.");
4064 public jalview.gui.AlignmentPanel copyAlignPanel(AlignmentPanel ap,
4065 boolean keepSeqRefs)
4068 jalview.schemabinding.version2.JalviewModel jm = SaveState(ap, null,
4074 jm.getJalviewModelSequence().getViewport(0).setSequenceSetId(null);
4078 uniqueSetSuffix = "";
4079 jm.getJalviewModelSequence().getViewport(0).setId(null); // we don't
4084 if (this.frefedSequence == null)
4086 frefedSequence = new Vector();
4089 viewportsAdded = new Hashtable();
4091 AlignFrame af = LoadFromObject(jm, null, false, null);
4092 af.alignPanels.clear();
4093 af.closeMenuItem_actionPerformed(true);
4096 * if(ap.av.getAlignment().getAlignmentAnnotation()!=null) { for(int i=0;
4097 * i<ap.av.getAlignment().getAlignmentAnnotation().length; i++) {
4098 * if(!ap.av.getAlignment().getAlignmentAnnotation()[i].autoCalculated) {
4099 * af.alignPanel.av.getAlignment().getAlignmentAnnotation()[i] =
4100 * ap.av.getAlignment().getAlignmentAnnotation()[i]; } } }
4103 return af.alignPanel;
4107 * flag indicating if hashtables should be cleared on finalization TODO this
4108 * flag may not be necessary
4110 private final boolean _cleartables = true;
4112 private Hashtable jvids2vobj;
4117 * @see java.lang.Object#finalize()
4120 protected void finalize() throws Throwable
4122 // really make sure we have no buried refs left.
4127 this.seqRefIds = null;
4128 this.seqsToIds = null;
4132 private void warn(String msg)
4137 private void warn(String msg, Exception e)
4139 if (Cache.log != null)
4143 Cache.log.warn(msg, e);
4147 Cache.log.warn(msg);
4152 System.err.println("Warning: " + msg);
4155 e.printStackTrace();
4160 private void debug(String string)
4162 debug(string, null);
4165 private void debug(String msg, Exception e)
4167 if (Cache.log != null)
4171 Cache.log.debug(msg, e);
4175 Cache.log.debug(msg);
4180 System.err.println("Warning: " + msg);
4183 e.printStackTrace();
4189 * set the object to ID mapping tables used to write/recover objects and XML
4190 * ID strings for the jalview project. If external tables are provided then
4191 * finalize and clearSeqRefs will not clear the tables when the Jalview2XML
4192 * object goes out of scope. - also populates the datasetIds hashtable with
4193 * alignment objects containing dataset sequences
4196 * Map from ID strings to jalview datamodel
4198 * Map from jalview datamodel to ID strings
4202 public void setObjectMappingTables(Hashtable vobj2jv,
4203 IdentityHashMap jv2vobj)
4205 this.jv2vobj = jv2vobj;
4206 this.vobj2jv = vobj2jv;
4207 Iterator ds = jv2vobj.keySet().iterator();
4209 while (ds.hasNext())
4211 Object jvobj = ds.next();
4212 id = jv2vobj.get(jvobj).toString();
4213 if (jvobj instanceof jalview.datamodel.Alignment)
4215 if (((jalview.datamodel.Alignment) jvobj).getDataset() == null)
4217 addDatasetRef(id, (jalview.datamodel.Alignment) jvobj);
4220 else if (jvobj instanceof jalview.datamodel.Sequence)
4222 // register sequence object so the XML parser can recover it.
4223 if (seqRefIds == null)
4225 seqRefIds = new Hashtable();
4227 if (seqsToIds == null)
4229 seqsToIds = new IdentityHashMap();
4231 seqRefIds.put(jv2vobj.get(jvobj).toString(), jvobj);
4232 seqsToIds.put(jvobj, id);
4234 else if (jvobj instanceof jalview.datamodel.AlignmentAnnotation)
4236 if (annotationIds == null)
4238 annotationIds = new Hashtable();
4241 annotationIds.put(anid = jv2vobj.get(jvobj).toString(), jvobj);
4242 jalview.datamodel.AlignmentAnnotation jvann = (jalview.datamodel.AlignmentAnnotation) jvobj;
4243 if (jvann.annotationId == null)
4245 jvann.annotationId = anid;
4247 if (!jvann.annotationId.equals(anid))
4249 // TODO verify that this is the correct behaviour
4250 this.warn("Overriding Annotation ID for " + anid
4251 + " from different id : " + jvann.annotationId);
4252 jvann.annotationId = anid;
4255 else if (jvobj instanceof String)
4257 if (jvids2vobj == null)
4259 jvids2vobj = new Hashtable();
4260 jvids2vobj.put(jvobj, jv2vobj.get(jvobj).toString());
4264 Cache.log.debug("Ignoring " + jvobj.getClass() + " (ID = " + id);
4269 * set the uniqueSetSuffix used to prefix/suffix object IDs for jalview
4270 * objects created from the project archive. If string is null (default for
4271 * construction) then suffix will be set automatically.
4275 public void setUniqueSetSuffix(String string)
4277 uniqueSetSuffix = string;
4282 * uses skipList2 as the skipList for skipping views on sequence sets
4283 * associated with keys in the skipList
4287 public void setSkipList(Hashtable skipList2)
4289 skipList = skipList2;