+ // Some other file here.
+ entryCount++;
+ }
+ } while (jarentry != null);
+ resolveFrefedSequences();
+ } catch (IOException ex)
+ {
+ ex.printStackTrace();
+ errorMessage = "Couldn't locate Jalview XML file : " + file;
+ System.err.println("Exception whilst loading jalview XML file : "
+ + ex + "\n");
+ } catch (Exception ex)
+ {
+ System.err.println("Parsing as Jalview Version 2 file failed.");
+ ex.printStackTrace(System.err);
+ if (attemptversion1parse)
+ {
+ // Is Version 1 Jar file?
+ try
+ {
+ af = new Jalview2XML_V1(raiseGUI).LoadJalviewAlign(jprovider);
+ } catch (Exception ex2)
+ {
+ System.err.println("Exception whilst loading as jalviewXMLV1:");
+ ex2.printStackTrace();
+ af = null;
+ }
+ }
+ if (Desktop.instance != null)
+ {
+ Desktop.instance.stopLoading();
+ }
+ if (af != null)
+ {
+ System.out.println("Successfully loaded archive file");
+ return af;
+ }
+ ex.printStackTrace();
+
+ System.err.println("Exception whilst loading jalview XML file : "
+ + ex + "\n");
+ } catch (OutOfMemoryError e)
+ {
+ // Don't use the OOM Window here
+ errorMessage = "Out of memory loading jalview XML file";
+ System.err.println("Out of memory whilst loading jalview XML file");
+ e.printStackTrace();
+ }
+
+ if (Desktop.instance != null)
+ {
+ Desktop.instance.stopLoading();
+ }
+
+ /*
+ * Regather multiple views (with the same sequence set id) to the frame (if
+ * any) that is flagged as the one to gather to, i.e. convert them to tabbed
+ * views instead of separate frames. Note this doesn't restore a state where
+ * some expanded views in turn have tabbed views - the last "first tab" read
+ * in will play the role of gatherer for all.
+ */
+ for (AlignFrame fr : gatherToThisFrame.values())
+ {
+ Desktop.instance.gatherViews(fr);
+ }
+
+ restoreSplitFrames();
+
+ if (errorMessage != null)
+ {
+ reportErrors();
+ }
+ return af;
+ }
+
+ /**
+ * Try to reconstruct and display SplitFrame windows, where each contains
+ * complementary dna and protein alignments. Done by pairing up AlignFrame
+ * objects (created earlier) which have complementary viewport ids associated.
+ */
+ protected void restoreSplitFrames()
+ {
+ List<SplitFrame> gatherTo = new ArrayList<SplitFrame>();
+ List<AlignFrame> addedToSplitFrames = new ArrayList<AlignFrame>();
+ Map<String, AlignFrame> dna = new HashMap<String, AlignFrame>();
+
+ /*
+ * Identify the DNA alignments
+ */
+ for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
+ .entrySet())
+ {
+ AlignFrame af = candidate.getValue();
+ if (af.getViewport().getAlignment().isNucleotide())
+ {
+ dna.put(candidate.getKey().getId(), af);
+ }
+ }
+
+ /*
+ * Try to match up the protein complements
+ */
+ for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
+ .entrySet())
+ {
+ AlignFrame af = candidate.getValue();
+ if (!af.getViewport().getAlignment().isNucleotide())
+ {
+ String complementId = candidate.getKey().getComplementId();
+ // only non-null complements should be in the Map
+ if (complementId != null && dna.containsKey(complementId))
+ {
+ final AlignFrame dnaFrame = dna.get(complementId);
+ SplitFrame sf = createSplitFrame(dnaFrame, af);
+ addedToSplitFrames.add(dnaFrame);
+ addedToSplitFrames.add(af);
+ if (af.viewport.isGatherViewsHere())
+ {
+ gatherTo.add(sf);
+ }
+ }
+ }
+ }
+
+ /*
+ * Open any that we failed to pair up (which shouldn't happen!) as
+ * standalone AlignFrame's.
+ */
+ for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
+ .entrySet())
+ {
+ AlignFrame af = candidate.getValue();
+ if (!addedToSplitFrames.contains(af))
+ {
+ Viewport view = candidate.getKey();
+ Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
+ view.getHeight());
+ System.err.println("Failed to restore view " + view.getTitle()
+ + " to split frame");
+ }
+ }
+
+ /*
+ * Gather back into tabbed views as flagged.
+ */
+ for (SplitFrame sf : gatherTo)
+ {
+ Desktop.instance.gatherViews(sf);
+ }
+
+ splitFrameCandidates.clear();
+ }
+
+ /**
+ * Construct and display one SplitFrame holding DNA and protein alignments.
+ *
+ * @param dnaFrame
+ * @param proteinFrame
+ * @return
+ */
+ protected SplitFrame createSplitFrame(AlignFrame dnaFrame,
+ AlignFrame proteinFrame)
+ {
+ SplitFrame splitFrame = new SplitFrame(dnaFrame, proteinFrame);
+ String title = MessageManager.getString("label.linked_view_title");
+ int width = (int) dnaFrame.getBounds().getWidth();
+ int height = (int) (dnaFrame.getBounds().getHeight()
+ + proteinFrame.getBounds().getHeight() + 50);
+
+ /*
+ * SplitFrame location is saved to both enclosed frames
+ */
+ splitFrame.setLocation(dnaFrame.getX(), dnaFrame.getY());
+ Desktop.addInternalFrame(splitFrame, title, width, height);
+
+ /*
+ * And compute cDNA consensus (couldn't do earlier with consensus as
+ * mappings were not yet present)
+ */
+ proteinFrame.viewport.alignmentChanged(proteinFrame.alignPanel);
+
+ return splitFrame;
+ }
+
+ /**
+ * check errorMessage for a valid error message and raise an error box in the
+ * GUI or write the current errorMessage to stderr and then clear the error
+ * state.
+ */
+ protected void reportErrors()
+ {
+ reportErrors(false);
+ }
+
+ protected void reportErrors(final boolean saving)
+ {
+ if (errorMessage != null)
+ {
+ final String finalErrorMessage = errorMessage;
+ if (raiseGUI)
+ {
+ javax.swing.SwingUtilities.invokeLater(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ JOptionPane.showInternalMessageDialog(Desktop.desktop,
+ finalErrorMessage, "Error "
+ + (saving ? "saving" : "loading")
+ + " Jalview file", JOptionPane.WARNING_MESSAGE);
+ }
+ });
+ }
+ else
+ {
+ System.err.println("Problem loading Jalview file: " + errorMessage);
+ }
+ }
+ errorMessage = null;
+ }
+
+ Map<String, String> alreadyLoadedPDB = new HashMap<String, String>();
+
+ /**
+ * when set, local views will be updated from view stored in JalviewXML
+ * Currently (28th Sep 2008) things will go horribly wrong in vamsas document
+ * sync if this is set to true.
+ */
+ private final boolean updateLocalViews = false;
+
+ /**
+ * Returns the path to a temporary file holding the PDB file for the given PDB
+ * id. The first time of asking, searches for a file of that name in the
+ * Jalview project jar, and copies it to a new temporary file. Any repeat
+ * requests just return the path to the file previously created.
+ *
+ * @param jprovider
+ * @param pdbId
+ * @return
+ */
+ String loadPDBFile(jarInputStreamProvider jprovider, String pdbId)
+ {
+ if (alreadyLoadedPDB.containsKey(pdbId))
+ {
+ return alreadyLoadedPDB.get(pdbId).toString();
+ }
+
+ String tempFile = copyJarEntry(jprovider, pdbId, "jalview_pdb");
+ if (tempFile != null)
+ {
+ alreadyLoadedPDB.put(pdbId, tempFile);
+ }
+ return tempFile;
+ }
+
+ /**
+ * Copies the jar entry of given name to a new temporary file and returns the
+ * path to the file, or null if the entry is not found.
+ *
+ * @param jprovider
+ * @param jarEntryName
+ * @param prefix
+ * a prefix for the temporary file name, must be at least three
+ * characters long
+ * @return
+ */
+ protected String copyJarEntry(jarInputStreamProvider jprovider,
+ String jarEntryName, String prefix)
+ {
+ BufferedReader in = null;
+ PrintWriter out = null;
+
+ try
+ {
+ JarInputStream jin = jprovider.getJarInputStream();
+ /*
+ * if (jprovider.startsWith("http://")) { jin = new JarInputStream(new
+ * URL(jprovider).openStream()); } else { jin = new JarInputStream(new
+ * FileInputStream(jprovider)); }
+ */
+
+ JarEntry entry = null;
+ do
+ {
+ entry = jin.getNextJarEntry();
+ } while (entry != null && !entry.getName().equals(jarEntryName));
+ if (entry != null)
+ {
+ in = new BufferedReader(new InputStreamReader(jin, UTF_8));
+ File outFile = File.createTempFile(prefix, ".tmp");
+ outFile.deleteOnExit();
+ out = new PrintWriter(new FileOutputStream(outFile));
+ String data;
+
+ while ((data = in.readLine()) != null)
+ {
+ out.println(data);
+ }
+ out.flush();
+ String t = outFile.getAbsolutePath();
+ return t;
+ }
+ else
+ {
+ warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
+ }
+ } catch (Exception ex)
+ {
+ ex.printStackTrace();
+ } finally
+ {
+ if (in != null)
+ {
+ try
+ {
+ in.close();
+ } catch (IOException e)
+ {
+ // ignore
+ }
+ }
+ if (out != null)
+ {
+ out.close();
+ }
+ }
+
+ return null;
+ }
+
+ private class JvAnnotRow
+ {
+ public JvAnnotRow(int i, AlignmentAnnotation jaa)
+ {
+ order = i;
+ template = jaa;
+ }
+
+ /**
+ * persisted version of annotation row from which to take vis properties
+ */
+ public jalview.datamodel.AlignmentAnnotation template;
+
+ /**
+ * original position of the annotation row in the alignment
+ */
+ public int order;
+ }
+
+ /**
+ * Load alignment frame from jalview XML DOM object
+ *
+ * @param object
+ * DOM
+ * @param file
+ * filename source string
+ * @param loadTreesAndStructures
+ * when false only create Viewport
+ * @param jprovider
+ * data source provider
+ * @return alignment frame created from view stored in DOM
+ */
+ AlignFrame loadFromObject(JalviewModel object, String file,
+ boolean loadTreesAndStructures, jarInputStreamProvider jprovider)
+ {
+ SequenceSet vamsasSet = object.getVamsasModel().getSequenceSet(0);
+ Sequence[] vamsasSeq = vamsasSet.getSequence();
+
+ JalviewModelSequence jms = object.getJalviewModelSequence();
+
+ Viewport view = (jms.getViewportCount() > 0) ? jms.getViewport(0)
+ : null;
+
+ // ////////////////////////////////
+ // LOAD SEQUENCES
+
+ List<SequenceI> hiddenSeqs = null;
+
+
+ List<SequenceI> tmpseqs = new ArrayList<SequenceI>();
+
+ boolean multipleView = false;
+ SequenceI referenceseqForView = null;
+ JSeq[] jseqs = object.getJalviewModelSequence().getJSeq();
+ int vi = 0; // counter in vamsasSeq array
+ for (int i = 0; i < jseqs.length; i++)
+ {
+ String seqId = jseqs[i].getId();
+
+ SequenceI tmpSeq = seqRefIds.get(seqId);
+ if (tmpSeq != null)
+ {
+ tmpSeq.setStart(jseqs[i].getStart());
+ tmpSeq.setEnd(jseqs[i].getEnd());
+ tmpseqs.add(tmpSeq);
+ multipleView = true;
+ }
+ else
+ {
+ tmpSeq = new jalview.datamodel.Sequence(vamsasSeq[vi].getName(),
+ vamsasSeq[vi].getSequence());
+ tmpSeq.setDescription(vamsasSeq[vi].getDescription());
+ tmpSeq.setStart(jseqs[i].getStart());
+ tmpSeq.setEnd(jseqs[i].getEnd());
+ tmpSeq.setVamsasId(uniqueSetSuffix + seqId);
+ seqRefIds.put(vamsasSeq[vi].getId(), tmpSeq);
+ tmpseqs.add(tmpSeq);
+ vi++;
+ }
+
+ if (jseqs[i].hasViewreference() && jseqs[i].getViewreference())
+ {
+ referenceseqForView = tmpseqs.get(tmpseqs.size() - 1);
+ }
+
+ if (jseqs[i].getHidden())
+ {
+ if (hiddenSeqs == null)
+ {
+ hiddenSeqs = new ArrayList<SequenceI>();
+ }
+
+ hiddenSeqs.add(tmpSeq);
+ }
+ }
+
+ // /
+ // Create the alignment object from the sequence set
+ // ///////////////////////////////
+ SequenceI[] orderedSeqs = tmpseqs
+ .toArray(new SequenceI[tmpseqs.size()]);
+
+ AlignmentI al = new Alignment(orderedSeqs);
+
+ if (referenceseqForView != null)
+ {
+ al.setSeqrep(referenceseqForView);
+ }
+ // / Add the alignment properties
+ for (int i = 0; i < vamsasSet.getSequenceSetPropertiesCount(); i++)
+ {
+ SequenceSetProperties ssp = vamsasSet.getSequenceSetProperties(i);
+ al.setProperty(ssp.getKey(), ssp.getValue());
+ }
+
+ // /
+ // SequenceFeatures are added to the DatasetSequence,
+ // so we must create or recover the dataset before loading features
+ // ///////////////////////////////
+ if (vamsasSet.getDatasetId() == null || vamsasSet.getDatasetId() == "")
+ {
+ // older jalview projects do not have a dataset id.
+ al.setDataset(null);
+ }
+ else
+ {
+ // recover dataset - passing on flag indicating if this a 'viewless'
+ // sequence set (a.k.a. a stored dataset for the project)
+ recoverDatasetFor(vamsasSet, al, object.getJalviewModelSequence()
+ .getViewportCount() == 0);
+ }
+ // ///////////////////////////////
+
+ Hashtable pdbloaded = new Hashtable(); // TODO nothing writes to this??
+ if (!multipleView)
+ {
+ // load sequence features, database references and any associated PDB
+ // structures for the alignment
+ for (int i = 0; i < vamsasSeq.length; i++)
+ {
+ if (jseqs[i].getFeaturesCount() > 0)
+ {
+ Features[] features = jseqs[i].getFeatures();
+ for (int f = 0; f < features.length; f++)
+ {
+ jalview.datamodel.SequenceFeature sf = new jalview.datamodel.SequenceFeature(
+ features[f].getType(), features[f].getDescription(),
+ features[f].getStatus(), features[f].getBegin(),
+ features[f].getEnd(), features[f].getFeatureGroup());
+
+ sf.setScore(features[f].getScore());
+ for (int od = 0; od < features[f].getOtherDataCount(); od++)
+ {
+ OtherData keyValue = features[f].getOtherData(od);
+ if (keyValue.getKey().startsWith("LINK"))
+ {
+ sf.addLink(keyValue.getValue());
+ }
+ else
+ {
+ sf.setValue(keyValue.getKey(), keyValue.getValue());
+ }
+
+ }
+
+ al.getSequenceAt(i).getDatasetSequence().addSequenceFeature(sf);
+ }
+ }
+ if (vamsasSeq[i].getDBRefCount() > 0)
+ {
+ addDBRefs(al.getSequenceAt(i).getDatasetSequence(), vamsasSeq[i]);
+ }
+ if (jseqs[i].getPdbidsCount() > 0)
+ {
+ Pdbids[] ids = jseqs[i].getPdbids();
+ for (int p = 0; p < ids.length; p++)
+ {
+ jalview.datamodel.PDBEntry entry = new jalview.datamodel.PDBEntry();
+ entry.setId(ids[p].getId());
+ if (ids[p].getType() != null)
+ {
+ if (ids[p].getType().equalsIgnoreCase("PDB"))
+ {
+ entry.setType(PDBEntry.Type.PDB);
+ }
+ else
+ {
+ entry.setType(PDBEntry.Type.FILE);
+ }
+ }
+ if (ids[p].getFile() != null)
+ {
+ if (!pdbloaded.containsKey(ids[p].getFile()))
+ {
+ entry.setFile(loadPDBFile(jprovider, ids[p].getId()));
+ }
+ else
+ {
+ entry.setFile(pdbloaded.get(ids[p].getId()).toString());
+ }
+ }
+ StructureSelectionManager.getStructureSelectionManager(
+ Desktop.instance).registerPDBEntry(entry);
+ al.getSequenceAt(i).getDatasetSequence().addPDBId(entry);
+ }
+ }
+ }
+ } // end !multipleview
+
+ // ///////////////////////////////
+ // LOAD SEQUENCE MAPPINGS
+
+ if (vamsasSet.getAlcodonFrameCount() > 0)
+ {
+ // TODO Potentially this should only be done once for all views of an
+ // alignment
+ AlcodonFrame[] alc = vamsasSet.getAlcodonFrame();
+ for (int i = 0; i < alc.length; i++)
+ {
+ AlignedCodonFrame cf = new AlignedCodonFrame();
+ if (alc[i].getAlcodMapCount() > 0)
+ {
+ AlcodMap[] maps = alc[i].getAlcodMap();
+ for (int m = 0; m < maps.length; m++)
+ {
+ SequenceI dnaseq = seqRefIds.get(maps[m].getDnasq());
+ // Load Mapping
+ jalview.datamodel.Mapping mapping = null;
+ // attach to dna sequence reference.
+ if (maps[m].getMapping() != null)
+ {
+ mapping = addMapping(maps[m].getMapping());
+ }
+ if (dnaseq != null && mapping.getTo() != null)
+ {
+ cf.addMap(dnaseq, mapping.getTo(), mapping.getMap());
+ }
+ else
+ {
+ // defer to later
+ frefedSequence.add(new Object[] { maps[m].getDnasq(), cf,
+ mapping });
+ }
+ }
+ al.addCodonFrame(cf);
+ }
+ }
+ }
+
+ // ////////////////////////////////
+ // LOAD ANNOTATIONS
+ List<JvAnnotRow> autoAlan = new ArrayList<JvAnnotRow>();
+
+ /*
+ * store any annotations which forward reference a group's ID
+ */
+ Map<String, List<AlignmentAnnotation>> groupAnnotRefs = new Hashtable<String, List<AlignmentAnnotation>>();
+
+ if (vamsasSet.getAnnotationCount() > 0)
+ {
+ Annotation[] an = vamsasSet.getAnnotation();
+
+ for (int i = 0; i < an.length; i++)
+ {
+ Annotation annotation = an[i];
+
+ /**
+ * test if annotation is automatically calculated for this view only
+ */
+ boolean autoForView = false;
+ if (annotation.getLabel().equals("Quality")
+ || annotation.getLabel().equals("Conservation")
+ || annotation.getLabel().equals("Consensus"))
+ {
+ // Kludge for pre 2.5 projects which lacked the autocalculated flag
+ autoForView = true;
+ if (!annotation.hasAutoCalculated())
+ {
+ annotation.setAutoCalculated(true);
+ }
+ }
+ if (autoForView
+ || (annotation.hasAutoCalculated() && annotation
+ .isAutoCalculated()))
+ {
+ // remove ID - we don't recover annotation from other views for
+ // view-specific annotation
+ annotation.setId(null);
+ }
+
+ // set visiblity for other annotation in this view
+ String annotationId = annotation.getId();
+ if (annotationId != null && annotationIds.containsKey(annotationId))
+ {
+ AlignmentAnnotation jda = annotationIds.get(annotationId);
+ // in principle Visible should always be true for annotation displayed
+ // in multiple views
+ if (annotation.hasVisible())
+ {
+ jda.visible = annotation.getVisible();
+ }
+
+ al.addAnnotation(jda);
+
+ continue;
+ }
+ // Construct new annotation from model.
+ AnnotationElement[] ae = annotation.getAnnotationElement();
+ jalview.datamodel.Annotation[] anot = null;
+ java.awt.Color firstColour = null;
+ int anpos;
+ if (!annotation.getScoreOnly())
+ {
+ anot = new jalview.datamodel.Annotation[al.getWidth()];
+ for (int aa = 0; aa < ae.length && aa < anot.length; aa++)
+ {
+ anpos = ae[aa].getPosition();
+
+ if (anpos >= anot.length)
+ {
+ continue;
+ }
+
+ anot[anpos] = new jalview.datamodel.Annotation(
+
+ ae[aa].getDisplayCharacter(), ae[aa].getDescription(),
+ (ae[aa].getSecondaryStructure() == null || ae[aa]
+ .getSecondaryStructure().length() == 0) ? ' '
+ : ae[aa].getSecondaryStructure().charAt(0),
+ ae[aa].getValue()
+
+ );
+ // JBPNote: Consider verifying dataflow for IO of secondary
+ // structure annotation read from Stockholm files
+ // this was added to try to ensure that
+ // if (anot[ae[aa].getPosition()].secondaryStructure>' ')
+ // {
+ // anot[ae[aa].getPosition()].displayCharacter = "";
+ // }
+ anot[anpos].colour = new java.awt.Color(ae[aa].getColour());
+ if (firstColour == null)
+ {
+ firstColour = anot[anpos].colour;
+ }
+ }
+ }
+ jalview.datamodel.AlignmentAnnotation jaa = null;
+
+ if (annotation.getGraph())
+ {
+ float llim = 0, hlim = 0;
+ // if (autoForView || an[i].isAutoCalculated()) {
+ // hlim=11f;
+ // }
+ jaa = new jalview.datamodel.AlignmentAnnotation(
+ annotation.getLabel(), annotation.getDescription(), anot,
+ llim, hlim, annotation.getGraphType());
+
+ jaa.graphGroup = annotation.getGraphGroup();
+ jaa._linecolour = firstColour;
+ if (annotation.getThresholdLine() != null)
+ {
+ jaa.setThreshold(new jalview.datamodel.GraphLine(annotation
+ .getThresholdLine().getValue(), annotation
+ .getThresholdLine().getLabel(), new java.awt.Color(
+ annotation.getThresholdLine().getColour())));
+
+ }
+ if (autoForView || annotation.isAutoCalculated())
+ {
+ // Hardwire the symbol display line to ensure that labels for
+ // histograms are displayed
+ jaa.hasText = true;
+ }
+ }
+ else
+ {
+ jaa = new jalview.datamodel.AlignmentAnnotation(an[i].getLabel(),
+ an[i].getDescription(), anot);
+ jaa._linecolour = firstColour;
+ }
+ // register new annotation
+ if (an[i].getId() != null)
+ {
+ annotationIds.put(an[i].getId(), jaa);
+ jaa.annotationId = an[i].getId();
+ }
+ // recover sequence association
+ String sequenceRef = an[i].getSequenceRef();
+ if (sequenceRef != null)
+ {
+ // from 2.9 sequenceRef is to sequence id (JAL-1781)
+ SequenceI sequence = seqRefIds.get(sequenceRef);
+ if (sequence == null)
+ {
+ // in pre-2.9 projects sequence ref is to sequence name
+ sequence = al.findName(sequenceRef);
+ }
+ if (sequence != null)
+ {
+ jaa.createSequenceMapping(sequence, 1, true);
+ sequence.addAlignmentAnnotation(jaa);
+ }
+ }
+ // and make a note of any group association
+ if (an[i].getGroupRef() != null && an[i].getGroupRef().length() > 0)
+ {
+ List<jalview.datamodel.AlignmentAnnotation> aal = groupAnnotRefs
+ .get(an[i].getGroupRef());
+ if (aal == null)
+ {
+ aal = new ArrayList<jalview.datamodel.AlignmentAnnotation>();
+ groupAnnotRefs.put(an[i].getGroupRef(), aal);
+ }
+ aal.add(jaa);
+ }
+
+ if (an[i].hasScore())
+ {
+ jaa.setScore(an[i].getScore());
+ }
+ if (an[i].hasVisible())
+ {
+ jaa.visible = an[i].getVisible();
+ }
+
+ if (an[i].hasCentreColLabels())
+ {
+ jaa.centreColLabels = an[i].getCentreColLabels();
+ }
+
+ if (an[i].hasScaleColLabels())
+ {
+ jaa.scaleColLabel = an[i].getScaleColLabels();
+ }
+ if (an[i].hasAutoCalculated() && an[i].isAutoCalculated())
+ {
+ // newer files have an 'autoCalculated' flag and store calculation
+ // state in viewport properties
+ jaa.autoCalculated = true; // means annotation will be marked for
+ // update at end of load.
+ }
+ if (an[i].hasGraphHeight())
+ {
+ jaa.graphHeight = an[i].getGraphHeight();
+ }
+ if (an[i].hasBelowAlignment())
+ {
+ jaa.belowAlignment = an[i].isBelowAlignment();
+ }
+ jaa.setCalcId(an[i].getCalcId());
+ if (an[i].getPropertyCount() > 0)
+ {
+ for (jalview.schemabinding.version2.Property prop : an[i]
+ .getProperty())
+ {
+ jaa.setProperty(prop.getName(), prop.getValue());
+ }
+ }
+ if (jaa.autoCalculated)
+ {
+ autoAlan.add(new JvAnnotRow(i, jaa));
+ }
+ else
+ // if (!autoForView)
+ {
+ // add autocalculated group annotation and any user created annotation
+ // for the view
+ al.addAnnotation(jaa);
+ }
+ }
+ }
+ // ///////////////////////
+ // LOAD GROUPS
+ // Create alignment markup and styles for this view
+ if (jms.getJGroupCount() > 0)
+ {
+ JGroup[] groups = jms.getJGroup();
+ boolean addAnnotSchemeGroup = false;
+ for (int i = 0; i < groups.length; i++)
+ {
+ JGroup jGroup = groups[i];
+ ColourSchemeI cs = null;
+ if (jGroup.getColour() != null)
+ {
+ if (jGroup.getColour().startsWith("ucs"))
+ {
+ cs = getUserColourScheme(jms, jGroup.getColour());
+ }
+ else if (jGroup.getColour().equals("AnnotationColourGradient")
+ && jGroup.getAnnotationColours() != null)
+ {
+ addAnnotSchemeGroup = true;
+ cs = null;
+ }
+ else
+ {
+ cs = ColourSchemeProperty.getColour(al, jGroup.getColour());
+ }
+
+ if (cs != null)
+ {
+ cs.setThreshold(jGroup.getPidThreshold(), true);
+ }
+ }
+
+ Vector<SequenceI> seqs = new Vector<SequenceI>();
+
+ for (int s = 0; s < jGroup.getSeqCount(); s++)
+ {
+ String seqId = jGroup.getSeq(s) + "";
+ SequenceI ts = seqRefIds.get(seqId);
+
+ if (ts != null)
+ {
+ seqs.addElement(ts);
+ }
+ }
+
+ if (seqs.size() < 1)
+ {
+ continue;
+ }
+
+ SequenceGroup sg = new SequenceGroup(seqs, jGroup.getName(), cs,
+ jGroup.getDisplayBoxes(), jGroup.getDisplayText(),
+ jGroup.getColourText(), jGroup.getStart(), jGroup.getEnd());
+
+ sg.setOutlineColour(new java.awt.Color(jGroup.getOutlineColour()));
+
+ sg.textColour = new java.awt.Color(jGroup.getTextCol1());
+ sg.textColour2 = new java.awt.Color(jGroup.getTextCol2());
+ sg.setShowNonconserved(jGroup.hasShowUnconserved() ? jGroup
+ .isShowUnconserved() : false);
+ sg.thresholdTextColour = jGroup.getTextColThreshold();
+ if (jGroup.hasShowConsensusHistogram())
+ {
+ sg.setShowConsensusHistogram(jGroup.isShowConsensusHistogram());
+ }
+ ;
+ if (jGroup.hasShowSequenceLogo())
+ {
+ sg.setshowSequenceLogo(jGroup.isShowSequenceLogo());
+ }
+ if (jGroup.hasNormaliseSequenceLogo())
+ {
+ sg.setNormaliseSequenceLogo(jGroup.isNormaliseSequenceLogo());
+ }
+ if (jGroup.hasIgnoreGapsinConsensus())
+ {
+ sg.setIgnoreGapsConsensus(jGroup.getIgnoreGapsinConsensus());
+ }
+ if (jGroup.getConsThreshold() != 0)
+ {
+ jalview.analysis.Conservation c = new jalview.analysis.Conservation(
+ "All", ResidueProperties.propHash, 3,
+ sg.getSequences(null), 0, sg.getWidth() - 1);
+ c.calculate();
+ c.verdict(false, 25);
+ sg.cs.setConservation(c);
+ }
+
+ if (jGroup.getId() != null && groupAnnotRefs.size() > 0)
+ {
+ // re-instate unique group/annotation row reference
+ List<AlignmentAnnotation> jaal = groupAnnotRefs.get(jGroup
+ .getId());
+ if (jaal != null)
+ {
+ for (AlignmentAnnotation jaa : jaal)
+ {
+ jaa.groupRef = sg;
+ if (jaa.autoCalculated)
+ {
+ // match up and try to set group autocalc alignment row for this
+ // annotation
+ if (jaa.label.startsWith("Consensus for "))
+ {
+ sg.setConsensus(jaa);
+ }
+ // match up and try to set group autocalc alignment row for this
+ // annotation
+ if (jaa.label.startsWith("Conservation for "))
+ {
+ sg.setConservationRow(jaa);
+ }
+ }
+ }
+ }
+ }
+ al.addGroup(sg);
+ if (addAnnotSchemeGroup)
+ {
+ // reconstruct the annotation colourscheme
+ sg.cs = constructAnnotationColour(jGroup.getAnnotationColours(),
+ null, al, jms, false);
+ }
+ }
+ }
+ if (view == null)
+ {
+ // only dataset in this model, so just return.
+ return null;
+ }
+ // ///////////////////////////////
+ // LOAD VIEWPORT
+
+ // If we just load in the same jar file again, the sequenceSetId
+ // will be the same, and we end up with multiple references
+ // to the same sequenceSet. We must modify this id on load
+ // so that each load of the file gives a unique id
+ String uniqueSeqSetId = view.getSequenceSetId() + uniqueSetSuffix;
+ String viewId = (view.getId() == null ? null : view.getId()
+ + uniqueSetSuffix);
+ AlignFrame af = null;
+ AlignViewport av = null;
+ // now check to see if we really need to create a new viewport.
+ if (multipleView && viewportsAdded.size() == 0)
+ {
+ // We recovered an alignment for which a viewport already exists.
+ // TODO: fix up any settings necessary for overlaying stored state onto
+ // state recovered from another document. (may not be necessary).
+ // we may need a binding from a viewport in memory to one recovered from
+ // XML.
+ // and then recover its containing af to allow the settings to be applied.
+ // TODO: fix for vamsas demo
+ System.err
+ .println("About to recover a viewport for existing alignment: Sequence set ID is "
+ + uniqueSeqSetId);
+ Object seqsetobj = retrieveExistingObj(uniqueSeqSetId);
+ if (seqsetobj != null)
+ {
+ if (seqsetobj instanceof String)
+ {
+ uniqueSeqSetId = (String) seqsetobj;
+ System.err
+ .println("Recovered extant sequence set ID mapping for ID : New Sequence set ID is "
+ + uniqueSeqSetId);
+ }
+ else
+ {
+ System.err
+ .println("Warning : Collision between sequence set ID string and existing jalview object mapping.");
+ }
+
+ }
+ }
+ /**
+ * indicate that annotation colours are applied across all groups (pre
+ * Jalview 2.8.1 behaviour)
+ */
+ boolean doGroupAnnColour = Jalview2XML.isVersionStringLaterThan(
+ "2.8.1", object.getVersion());
+
+ AlignmentPanel ap = null;
+ boolean isnewview = true;
+ if (viewId != null)
+ {
+ // Check to see if this alignment already has a view id == viewId
+ jalview.gui.AlignmentPanel views[] = Desktop
+ .getAlignmentPanels(uniqueSeqSetId);
+ if (views != null && views.length > 0)
+ {
+ for (int v = 0; v < views.length; v++)
+ {
+ if (views[v].av.getViewId().equalsIgnoreCase(viewId))
+ {
+ // recover the existing alignpanel, alignframe, viewport
+ af = views[v].alignFrame;
+ av = views[v].av;
+ ap = views[v];
+ // TODO: could even skip resetting view settings if we don't want to
+ // change the local settings from other jalview processes
+ isnewview = false;
+ }
+ }
+ }
+ }
+
+ if (isnewview)
+ {
+ af = loadViewport(file, jseqs, hiddenSeqs, al, jms, view,
+ uniqueSeqSetId, viewId, autoAlan);
+ av = af.viewport;
+ ap = af.alignPanel;
+ }
+
+ /*
+ * Load any trees, PDB structures and viewers
+ *
+ * Not done if flag is false (when this method is used for New View)
+ */
+ if (loadTreesAndStructures)
+ {
+ loadTrees(jms, view, af, av, ap);
+ loadPDBStructures(jprovider, jseqs, af, ap);
+ loadRnaViewers(jprovider, jseqs, ap);
+ }
+ // and finally return.
+ return af;
+ }
+
+ /**
+ * Instantiate and link any saved RNA (Varna) viewers. The state of the Varna
+ * panel is restored from separate jar entries, two (gapped and trimmed) per
+ * sequence and secondary structure.
+ *
+ * Currently each viewer shows just one sequence and structure (gapped and
+ * trimmed), however this method is designed to support multiple sequences or
+ * structures in viewers if wanted in future.
+ *
+ * @param jprovider
+ * @param jseqs
+ * @param ap
+ */
+ private void loadRnaViewers(jarInputStreamProvider jprovider,
+ JSeq[] jseqs, AlignmentPanel ap)
+ {
+ /*
+ * scan the sequences for references to viewers; create each one the first
+ * time it is referenced, add Rna models to existing viewers
+ */
+ for (JSeq jseq : jseqs)
+ {
+ for (int i = 0; i < jseq.getRnaViewerCount(); i++)
+ {
+ RnaViewer viewer = jseq.getRnaViewer(i);
+ AppVarna appVarna = findOrCreateVarnaViewer(viewer,
+ uniqueSetSuffix, ap);
+
+ for (int j = 0; j < viewer.getSecondaryStructureCount(); j++)
+ {
+ SecondaryStructure ss = viewer.getSecondaryStructure(j);
+ SequenceI seq = seqRefIds.get(jseq.getId());
+ AlignmentAnnotation ann = this.annotationIds.get(ss
+ .getAnnotationId());
+
+ /*
+ * add the structure to the Varna display (with session state copied
+ * from the jar to a temporary file)
+ */
+ boolean gapped = ss.isGapped();
+ String rnaTitle = ss.getTitle();
+ String sessionState = ss.getViewerState();
+ String tempStateFile = copyJarEntry(jprovider, sessionState,
+ "varna");
+ RnaModel rna = new RnaModel(rnaTitle, ann, seq, null, gapped);
+ appVarna.addModelSession(rna, rnaTitle, tempStateFile);
+ }
+ appVarna.setInitialSelection(viewer.getSelectedRna());
+ }
+ }
+ }
+
+ /**
+ * Locate and return an already instantiated matching AppVarna, or create one
+ * if not found
+ *
+ * @param viewer
+ * @param viewIdSuffix
+ * @param ap
+ * @return
+ */
+ protected AppVarna findOrCreateVarnaViewer(RnaViewer viewer,
+ String viewIdSuffix, AlignmentPanel ap)
+ {
+ /*
+ * on each load a suffix is appended to the saved viewId, to avoid conflicts
+ * if load is repeated
+ */
+ String postLoadId = viewer.getViewId() + viewIdSuffix;
+ for (JInternalFrame frame : getAllFrames())
+ {
+ if (frame instanceof AppVarna)
+ {
+ AppVarna varna = (AppVarna) frame;
+ if (postLoadId.equals(varna.getViewId()))
+ {
+ // this viewer is already instantiated
+ // could in future here add ap as another 'parent' of the
+ // AppVarna window; currently just 1-to-many
+ return varna;