+ if (comp == null)
+ {
+ // create a new Jmol window.
+ // First parse the Jmol state to translate filenames loaded into the
+ // view, and record the order in which files are shown in the Jmol
+ // view, so we can add the sequence mappings in same order.
+ StringBuffer newFileLoc = null;
+ int cp = 0, ncp, ecp;
+ while ((ncp = state.indexOf("load ", cp)) > -1)
+ {
+ if (newFileLoc == null)
+ {
+ newFileLoc = new StringBuffer();
+ }
+ do
+ {
+ // look for next filename in load statement
+ newFileLoc.append(state.substring(cp,
+ ncp = (state.indexOf("\"", ncp + 1) + 1)));
+ String oldfilenam = state.substring(ncp,
+ ecp = state.indexOf("\"", ncp));
+ // recover the new mapping data for this old filename
+ // have to normalize filename - since Jmol and jalview do
+ // filename
+ // translation differently.
+ Object[] filedat = oldFiles.get(new File(oldfilenam));
+ newFileLoc.append(Platform
+ .escapeString((String) filedat[0]));
+ pdbfilenames.addElement((String) filedat[0]);
+ pdbids.addElement((String) filedat[1]);
+ seqmaps.addElement(((Vector<SequenceI>) filedat[2])
+ .toArray(new SequenceI[0]));
+ newFileLoc.append("\"");
+ cp = ecp + 1; // advance beyond last \" and set cursor so we can
+ // look for next file statement.
+ } while ((ncp = state.indexOf("/*file*/", cp)) > -1);
+ }
+ if (cp > 0)
+ {
+ // just append rest of state
+ newFileLoc.append(state.substring(cp));
+ }
+ else
+ {
+ System.err
+ .print("Ignoring incomplete Jmol state for PDB ids: ");
+ newFileLoc = new StringBuffer(state);
+ newFileLoc.append("; load append ");
+ for (File id : oldFiles.keySet())
+ {
+ // add this and any other pdb files that should be present in
+ // the viewer
+ Object[] filedat = oldFiles.get(id);
+ String nfilename;
+ newFileLoc.append(((String) filedat[0]));
+ pdbfilenames.addElement((String) filedat[0]);
+ pdbids.addElement((String) filedat[1]);
+ seqmaps.addElement(((Vector<SequenceI>) filedat[2])
+ .toArray(new SequenceI[0]));
+ newFileLoc.append(" \"");
+ newFileLoc.append((String) filedat[0]);
+ newFileLoc.append("\"");
+
+ }
+ newFileLoc.append(";");
+ }
+
+ if (newFileLoc != null)
+ {
+ int histbug = newFileLoc.indexOf("history = ");
+ histbug += 10;
+ int diff = histbug == -1 ? -1 : newFileLoc.indexOf(";",
+ histbug);
+ String val = (diff == -1) ? null : newFileLoc.substring(
+ histbug, diff);
+ if (val != null && val.length() >= 4)
+ {
+ if (val.contains("e"))
+ {
+ if (val.trim().equals("true"))
+ {
+ val = "1";
+ }
+ else
+ {
+ val = "0";
+ }
+ newFileLoc.replace(histbug, diff, val);
+ }
+ }
+ // TODO: assemble String[] { pdb files }, String[] { id for each
+ // file }, orig_fileloc, SequenceI[][] {{ seqs_file 1 }, {
+ // seqs_file 2}} from hash
+ final String[] pdbf = pdbfilenames
+ .toArray(new String[pdbfilenames.size()]), id = pdbids
+ .toArray(new String[pdbids.size()]);
+ final SequenceI[][] sq = seqmaps
+ .toArray(new SequenceI[seqmaps.size()][]);
+ final String fileloc = newFileLoc.toString(), vid = sviewid;
+ final AlignFrame alf = af;
+ final java.awt.Rectangle rect = new java.awt.Rectangle(x, y,
+ width, height);
+ try
+ {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ AppJmol sview = null;
+ try
+ {
+ sview = new AppJmol(pdbf, id, sq, alf.alignPanel,
+ useinJmolsuperpos, usetoColourbyseq,
+ jmolColouring, fileloc, rect, vid);
+ addNewStructureViewer(sview);
+ } catch (OutOfMemoryError ex)
+ {
+ new OOMWarning("restoring structure view for PDB id "
+ + id, (OutOfMemoryError) ex.getCause());
+ if (sview != null && sview.isVisible())
+ {
+ sview.closeViewer();
+ sview.setVisible(false);
+ sview.dispose();
+ }
+ }
+ }
+ });
+ } catch (InvocationTargetException ex)
+ {
+ warn("Unexpected error when opening Jmol view.", ex);
+
+ } catch (InterruptedException e)
+ {
+ // e.printStackTrace();
+ }
+ }
+
+ }
+ else
+ // if (comp != null)
+ {
+ // NOTE: if the jalview project is part of a shared session then
+ // view synchronization should/could be done here.
+
+ // add mapping for sequences in this view to an already open Jmol
+ // instance
+ for (File id : oldFiles.keySet())
+ {
+ // add this and any other pdb files that should be present in the
+ // viewer
+ Object[] filedat = oldFiles.get(id);
+ String pdbFile = (String) filedat[0];
+ SequenceI[] seq = ((Vector<SequenceI>) filedat[2])
+ .toArray(new SequenceI[0]);
+ comp.jmb.ssm.setMapping(seq, null, pdbFile,
+ jalview.io.AppletFormatAdapter.FILE);
+ comp.jmb.addSequenceForStructFile(pdbFile, seq);
+ }
+ // and add the AlignmentPanel's reference to the Jmol view
+ comp.addAlignmentPanel(ap);
+ if (useinJmolsuperpos)
+ {
+ comp.useAlignmentPanelForSuperposition(ap);
+ }
+ else
+ {
+ comp.excludeAlignmentPanelForSuperposition(ap);
+ }
+ if (usetoColourbyseq)
+ {
+ comp.useAlignmentPanelForColourbyseq(ap, !jmolColouring);
+ }
+ else
+ {
+ comp.excludeAlignmentPanelForColourbyseq(ap);
+ }
+ }
+ }
+ }
+ }
+ // and finally return.
+ return af;
+ }
+ Vector<AppJmol> newStructureViewers=null;
+ protected void addNewStructureViewer(AppJmol sview)
+ {
+ if (newStructureViewers!=null)
+ {
+ sview.jmb.setFinishedLoadingFromArchive(false);
+ newStructureViewers.add(sview);
+ }
+ }
+ protected void setLoadingFinishedForNewStructureViewers()
+ {
+ if (newStructureViewers!=null)
+ {
+ for (AppJmol sview:newStructureViewers)
+ {
+ sview.jmb.setFinishedLoadingFromArchive(true);
+ }
+ newStructureViewers.clear();
+ newStructureViewers=null;
+ }
+ }
+
+ AlignFrame loadViewport(String file, JSeq[] JSEQ, Vector hiddenSeqs,
+ Alignment al, JalviewModelSequence jms, Viewport view,
+ String uniqueSeqSetId, String viewId,
+ ArrayList<JvAnnotRow> autoAlan)
+ {
+ AlignFrame af = null;
+ af = new AlignFrame(al, view.getWidth(), view.getHeight(),
+ uniqueSeqSetId, viewId);
+
+ af.setFileName(file, "Jalview");
+
+ for (int i = 0; i < JSEQ.length; i++)
+ {
+ af.viewport.setSequenceColour(af.viewport.getAlignment()
+ .getSequenceAt(i), new java.awt.Color(JSEQ[i].getColour()));
+ }
+
+ af.viewport.gatherViewsHere = view.getGatheredViews();
+
+ if (view.getSequenceSetId() != null)
+ {
+ jalview.gui.AlignViewport av = (jalview.gui.AlignViewport) viewportsAdded
+ .get(uniqueSeqSetId);
+
+ af.viewport.setSequenceSetId(uniqueSeqSetId);
+ if (av != null)
+ {
+ // propagate shared settings to this new view
+ af.viewport.historyList = av.historyList;
+ af.viewport.redoList = av.redoList;
+ }
+ else
+ {
+ viewportsAdded.put(uniqueSeqSetId, af.viewport);
+ }
+ // TODO: check if this method can be called repeatedly without
+ // side-effects if alignpanel already registered.
+ PaintRefresher.Register(af.alignPanel, uniqueSeqSetId);
+ }
+ // apply Hidden regions to view.
+ if (hiddenSeqs != null)
+ {
+ for (int s = 0; s < JSEQ.length; s++)
+ {
+ jalview.datamodel.SequenceGroup hidden = new jalview.datamodel.SequenceGroup();
+
+ for (int r = 0; r < JSEQ[s].getHiddenSequencesCount(); r++)
+ {
+ hidden.addSequence(
+ al.getSequenceAt(JSEQ[s].getHiddenSequences(r)), false);
+ }
+ af.viewport.hideRepSequences(al.getSequenceAt(s), hidden);
+ }
+
+ jalview.datamodel.SequenceI[] hseqs = new jalview.datamodel.SequenceI[hiddenSeqs
+ .size()];
+
+ for (int s = 0; s < hiddenSeqs.size(); s++)
+ {
+ hseqs[s] = (jalview.datamodel.SequenceI) hiddenSeqs.elementAt(s);
+ }
+
+ af.viewport.hideSequence(hseqs);
+
+ }
+ // recover view properties and display parameters
+ if (view.getViewName() != null)
+ {
+ af.viewport.viewName = view.getViewName();
+ af.setInitialTabVisible();
+ }
+ af.setBounds(view.getXpos(), view.getYpos(), view.getWidth(),
+ view.getHeight());
+
+ af.viewport.setShowAnnotation(view.getShowAnnotation());
+ af.viewport.setAbovePIDThreshold(view.getPidSelected());
+
+ af.viewport.setColourText(view.getShowColourText());
+
+ af.viewport.setConservationSelected(view.getConservationSelected());
+ af.viewport.setShowJVSuffix(view.getShowFullId());
+ af.viewport.rightAlignIds = view.getRightAlignIds();
+ af.viewport.setFont(new java.awt.Font(view.getFontName(), view
+ .getFontStyle(), view.getFontSize()));
+ af.alignPanel.fontChanged();
+ af.viewport.setRenderGaps(view.getRenderGaps());
+ af.viewport.setWrapAlignment(view.getWrapAlignment());
+ af.alignPanel.setWrapAlignment(view.getWrapAlignment());
+ af.viewport.setShowAnnotation(view.getShowAnnotation());
+ af.alignPanel.setAnnotationVisible(view.getShowAnnotation());
+
+ af.viewport.setShowBoxes(view.getShowBoxes());
+
+ af.viewport.setShowText(view.getShowText());
+
+ af.viewport.textColour = new java.awt.Color(view.getTextCol1());
+ af.viewport.textColour2 = new java.awt.Color(view.getTextCol2());
+ af.viewport.thresholdTextColour = view.getTextColThreshold();
+ af.viewport.setShowUnconserved(view.hasShowUnconserved() ? view
+ .isShowUnconserved() : false);
+ af.viewport.setStartRes(view.getStartRes());
+ af.viewport.setStartSeq(view.getStartSeq());
+
+ ColourSchemeI cs = null;
+ // apply colourschemes
+ if (view.getBgColour() != null)
+ {
+ if (view.getBgColour().startsWith("ucs"))
+ {
+ cs = GetUserColourScheme(jms, view.getBgColour());
+ }
+ else if (view.getBgColour().startsWith("Annotation"))
+ {
+ // int find annotation
+ if (af.viewport.getAlignment().getAlignmentAnnotation() != null)
+ {
+ for (int i = 0; i < af.viewport.getAlignment()
+ .getAlignmentAnnotation().length; i++)
+ {
+ if (af.viewport.getAlignment().getAlignmentAnnotation()[i].label
+ .equals(view.getAnnotationColours().getAnnotation()))
+ {
+ if (af.viewport.getAlignment().getAlignmentAnnotation()[i]
+ .getThreshold() == null)
+ {
+ af.viewport.getAlignment().getAlignmentAnnotation()[i]
+ .setThreshold(new jalview.datamodel.GraphLine(view
+ .getAnnotationColours().getThreshold(),
+ "Threshold", java.awt.Color.black)
+
+ );
+ }
+
+ if (view.getAnnotationColours().getColourScheme()
+ .equals("None"))
+ {
+ cs = new AnnotationColourGradient(af.viewport
+ .getAlignment().getAlignmentAnnotation()[i],
+ new java.awt.Color(view.getAnnotationColours()
+ .getMinColour()), new java.awt.Color(view
+ .getAnnotationColours().getMaxColour()),
+ view.getAnnotationColours().getAboveThreshold());
+ }
+ else if (view.getAnnotationColours().getColourScheme()
+ .startsWith("ucs"))
+ {
+ cs = new AnnotationColourGradient(af.viewport
+ .getAlignment().getAlignmentAnnotation()[i],
+ GetUserColourScheme(jms, view
+ .getAnnotationColours().getColourScheme()),
+ view.getAnnotationColours().getAboveThreshold());
+ }
+ else
+ {
+ cs = new AnnotationColourGradient(af.viewport
+ .getAlignment().getAlignmentAnnotation()[i],
+ ColourSchemeProperty.getColour(al, view
+ .getAnnotationColours().getColourScheme()),
+ view.getAnnotationColours().getAboveThreshold());
+ }
+
+ // Also use these settings for all the groups
+ if (al.getGroups() != null)
+ {
+ for (int g = 0; g < al.getGroups().size(); g++)
+ {
+ jalview.datamodel.SequenceGroup sg = al.getGroups()
+ .get(g);
+
+ if (sg.cs == null)
+ {
+ continue;
+ }
+
+ /*
+ * if
+ * (view.getAnnotationColours().getColourScheme().equals("None"
+ * )) { sg.cs = new AnnotationColourGradient(
+ * af.viewport.getAlignment().getAlignmentAnnotation()[i], new
+ * java.awt.Color(view.getAnnotationColours().
+ * getMinColour()), new
+ * java.awt.Color(view.getAnnotationColours().
+ * getMaxColour()),
+ * view.getAnnotationColours().getAboveThreshold()); } else
+ */
+ {
+ sg.cs = new AnnotationColourGradient(af.viewport
+ .getAlignment().getAlignmentAnnotation()[i],
+ sg.cs, view.getAnnotationColours()
+ .getAboveThreshold());
+ }
+
+ }
+ }
+
+ break;
+ }
+
+ }
+ }
+ }
+ else
+ {
+ cs = ColourSchemeProperty.getColour(al, view.getBgColour());
+ }
+
+ if (cs != null)
+ {
+ cs.setThreshold(view.getPidThreshold(), true);
+ cs.setConsensus(af.viewport.getSequenceConsensusHash());
+ }
+ }
+
+ af.viewport.setGlobalColourScheme(cs);
+ af.viewport.setColourAppliesToAllGroups(false);
+
+ if (view.getConservationSelected() && cs != null)
+ {
+ cs.setConservationInc(view.getConsThreshold());
+ }
+
+ af.changeColour(cs);
+
+ af.viewport.setColourAppliesToAllGroups(true);
+
+ if (view.getShowSequenceFeatures())
+ {
+ af.viewport.showSequenceFeatures = true;
+ }
+ if (view.hasCentreColumnLabels())
+ {
+ af.viewport.setCentreColumnLabels(view.getCentreColumnLabels());
+ }
+ if (view.hasIgnoreGapsinConsensus())
+ {
+ af.viewport.setIgnoreGapsConsensus(view.getIgnoreGapsinConsensus(),
+ null);
+ }
+ if (view.hasFollowHighlight())
+ {
+ af.viewport.followHighlight = view.getFollowHighlight();
+ }
+ if (view.hasFollowSelection())
+ {
+ af.viewport.followSelection = view.getFollowSelection();
+ }
+ if (view.hasShowConsensusHistogram())
+ {
+ af.viewport.setShowConsensusHistogram(view
+ .getShowConsensusHistogram());
+ }
+ else
+ {
+ af.viewport.setShowConsensusHistogram(true);
+ }
+ if (view.hasShowSequenceLogo())
+ {
+ af.viewport.setShowSequenceLogo(view.getShowSequenceLogo());
+ }
+ else
+ {
+ af.viewport.setShowSequenceLogo(false);
+ }
+ if (view.hasNormaliseSequenceLogo())
+ {
+ af.viewport.setNormaliseSequenceLogo(view.getNormaliseSequenceLogo());
+ }
+ if (view.hasShowDbRefTooltip())
+ {
+ af.viewport.setShowDbRefs(view.getShowDbRefTooltip());
+ }
+ if (view.hasShowNPfeatureTooltip())
+ {
+ af.viewport.setShowNpFeats(view.hasShowNPfeatureTooltip());
+ }
+ if (view.hasShowGroupConsensus())
+ {
+ af.viewport.setShowGroupConsensus(view.getShowGroupConsensus());
+ }
+ else
+ {
+ af.viewport.setShowGroupConsensus(false);
+ }
+ if (view.hasShowGroupConservation())
+ {
+ af.viewport.setShowGroupConservation(view.getShowGroupConservation());
+ }
+ else
+ {
+ af.viewport.setShowGroupConservation(false);
+ }
+
+ // recover featre settings
+ if (jms.getFeatureSettings() != null)
+ {
+ af.viewport.featuresDisplayed = new Hashtable();
+ String[] renderOrder = new String[jms.getFeatureSettings()
+ .getSettingCount()];
+ for (int fs = 0; fs < jms.getFeatureSettings().getSettingCount(); fs++)
+ {
+ Setting setting = jms.getFeatureSettings().getSetting(fs);
+ if (setting.hasMincolour())
+ {
+ GraduatedColor gc = setting.hasMin() ? new GraduatedColor(
+ new java.awt.Color(setting.getMincolour()),
+ new java.awt.Color(setting.getColour()),
+ setting.getMin(), setting.getMax()) : new GraduatedColor(
+ new java.awt.Color(setting.getMincolour()),
+ new java.awt.Color(setting.getColour()), 0, 1);
+ if (setting.hasThreshold())
+ {
+ gc.setThresh(setting.getThreshold());
+ gc.setThreshType(setting.getThreshstate());
+ }
+ gc.setAutoScaled(true); // default
+ if (setting.hasAutoScale())
+ {
+ gc.setAutoScaled(setting.getAutoScale());
+ }
+ if (setting.hasColourByLabel())
+ {
+ gc.setColourByLabel(setting.getColourByLabel());
+ }
+ // and put in the feature colour table.
+ af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().setColour(
+ setting.getType(), gc);
+ }
+ else
+ {
+ af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().setColour(
+ setting.getType(),
+ new java.awt.Color(setting.getColour()));
+ }
+ renderOrder[fs] = setting.getType();
+ if (setting.hasOrder())
+ af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().setOrder(
+ setting.getType(), setting.getOrder());
+ else
+ af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().setOrder(
+ setting.getType(),
+ fs / jms.getFeatureSettings().getSettingCount());
+ if (setting.getDisplay())
+ {
+ af.viewport.featuresDisplayed.put(setting.getType(), new Integer(
+ setting.getColour()));
+ }
+ }
+ af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().renderOrder = renderOrder;
+ Hashtable fgtable;
+ af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().featureGroups = fgtable = new Hashtable();
+ for (int gs = 0; gs < jms.getFeatureSettings().getGroupCount(); gs++)
+ {
+ Group grp = jms.getFeatureSettings().getGroup(gs);
+ fgtable.put(grp.getName(), new Boolean(grp.getDisplay()));
+ }
+ }
+
+ if (view.getHiddenColumnsCount() > 0)
+ {
+ for (int c = 0; c < view.getHiddenColumnsCount(); c++)
+ {
+ af.viewport.hideColumns(view.getHiddenColumns(c).getStart(), view
+ .getHiddenColumns(c).getEnd() // +1
+ );
+ }
+ }
+ if (view.getCalcIdParam() != null)
+ {
+ for (CalcIdParam calcIdParam : view.getCalcIdParam())
+ {
+ if (calcIdParam != null)
+ {
+ if (recoverCalcIdParam(calcIdParam, af.viewport))
+ {
+ }
+ else
+ {
+ warn("Couldn't recover parameters for "
+ + calcIdParam.getCalcId());
+ }
+ }
+ }
+ }
+ af.setMenusFromViewport(af.viewport);
+ // TODO: we don't need to do this if the viewport is aready visible.
+ Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
+ view.getHeight());
+ af.alignPanel.updateAnnotation(false, true); // recompute any autoannotation
+ reorderAutoannotation(af, al, autoAlan);
+ return af;
+ }
+
+ private void reorderAutoannotation(AlignFrame af, Alignment al,
+ ArrayList<JvAnnotRow> autoAlan)
+ {
+ // copy over visualization settings for autocalculated annotation in the
+ // view
+ if (al.getAlignmentAnnotation() != null)
+ {
+ /**
+ * Kludge for magic autoannotation names (see JAL-811)
+ */
+ String[] magicNames = new String[]
+ { "Consensus", "Quality", "Conservation" };
+ JvAnnotRow nullAnnot = new JvAnnotRow(-1, null);
+ Hashtable<String, JvAnnotRow> visan = new Hashtable<String, JvAnnotRow>();
+ for (String nm : magicNames)
+ {
+ visan.put(nm, nullAnnot);
+ }
+ for (JvAnnotRow auan : autoAlan)
+ {
+ visan.put(auan.template.label
+ + (auan.template.getCalcId() == null ? "" : "\t"
+ + auan.template.getCalcId()), auan);
+ }
+ int hSize = al.getAlignmentAnnotation().length;
+ ArrayList<JvAnnotRow> reorder = new ArrayList<JvAnnotRow>();
+ // work through any autoCalculated annotation already on the view
+ // removing it if it should be placed in a different location on the
+ // annotation panel.
+ List<String> remains = new ArrayList(visan.keySet());
+ for (int h = 0; h < hSize; h++)
+ {
+ jalview.datamodel.AlignmentAnnotation jalan = al
+ .getAlignmentAnnotation()[h];
+ if (jalan.autoCalculated)
+ {
+ String k;
+ JvAnnotRow valan = visan.get(k = jalan.label);
+ if (jalan.getCalcId() != null)
+ {
+ valan = visan.get(k = jalan.label + "\t" + jalan.getCalcId());
+ }
+
+ if (valan != null)
+ {
+ // delete the auto calculated row from the alignment
+ al.deleteAnnotation(jalan, false);
+ remains.remove(k);
+ hSize--;
+ h--;
+ if (valan != nullAnnot)
+ {
+ if (jalan != valan.template)
+ {
+ // newly created autoannotation row instance
+ // so keep a reference to the visible annotation row
+ // and copy over all relevant attributes
+ if (valan.template.graphHeight >= 0)
+
+ {
+ jalan.graphHeight = valan.template.graphHeight;
+ }
+ jalan.visible = valan.template.visible;
+ }
+ reorder.add(new JvAnnotRow(valan.order, jalan));
+ }
+ }
+ }
+ }
+ // Add any (possibly stale) autocalculated rows that were not appended to
+ // the view during construction
+ for (String other : remains)
+ {
+ JvAnnotRow othera = visan.get(other);
+ if (othera != nullAnnot && othera.template.getCalcId() != null
+ && othera.template.getCalcId().length() > 0)
+ {
+ reorder.add(othera);
+ }
+ }
+ // now put the automatic annotation in its correct place
+ int s = 0, srt[] = new int[reorder.size()];
+ JvAnnotRow[] rws = new JvAnnotRow[reorder.size()];
+ for (JvAnnotRow jvar : reorder)
+ {
+ rws[s] = jvar;
+ srt[s++] = jvar.order;
+ }
+ reorder.clear();
+ jalview.util.QuickSort.sort(srt, rws);
+ // and re-insert the annotation at its correct position
+ for (JvAnnotRow jvar : rws)
+ {
+ al.addAnnotation(jvar.template, jvar.order);
+ }
+ af.alignPanel.adjustAnnotationHeight();
+ }
+ }
+
+ Hashtable skipList = null;
+
+ /**
+ * TODO remove this method
+ *
+ * @param view
+ * @return AlignFrame bound to sequenceSetId from view, if one exists. private
+ * AlignFrame getSkippedFrame(Viewport view) { if (skipList==null) {
+ * throw new Error("Implementation Error. No skipList defined for this
+ * Jalview2XML instance."); } return (AlignFrame)
+ * skipList.get(view.getSequenceSetId()); }
+ */
+
+ /**
+ * Check if the Jalview view contained in object should be skipped or not.
+ *
+ * @param object
+ * @return true if view's sequenceSetId is a key in skipList
+ */
+ private boolean skipViewport(JalviewModel object)
+ {
+ if (skipList == null)
+ {
+ return false;
+ }
+ String id;
+ if (skipList.containsKey(id = object.getJalviewModelSequence()
+ .getViewport()[0].getSequenceSetId()))
+ {
+ if (Cache.log != null && Cache.log.isDebugEnabled())
+ {
+ Cache.log.debug("Skipping seuqence set id " + id);
+ }
+ return true;
+ }
+ return false;
+ }
+
+ public void AddToSkipList(AlignFrame af)
+ {
+ if (skipList == null)
+ {
+ skipList = new Hashtable();
+ }
+ skipList.put(af.getViewport().getSequenceSetId(), af);
+ }
+
+ public void clearSkipList()
+ {
+ if (skipList != null)
+ {
+ skipList.clear();
+ skipList = null;
+ }
+ }
+
+ private void recoverDatasetFor(SequenceSet vamsasSet, Alignment al)
+ {
+ jalview.datamodel.Alignment ds = getDatasetFor(vamsasSet.getDatasetId());
+ Vector dseqs = null;
+ if (ds == null)
+ {
+ // create a list of new dataset sequences
+ dseqs = new Vector();
+ }
+ for (int i = 0, iSize = vamsasSet.getSequenceCount(); i < iSize; i++)
+ {
+ Sequence vamsasSeq = vamsasSet.getSequence(i);
+ ensureJalviewDatasetSequence(vamsasSeq, ds, dseqs);
+ }
+ // create a new dataset
+ if (ds == null)
+ {
+ SequenceI[] dsseqs = new SequenceI[dseqs.size()];
+ dseqs.copyInto(dsseqs);
+ ds = new jalview.datamodel.Alignment(dsseqs);
+ debug("Created new dataset " + vamsasSet.getDatasetId()
+ + " for alignment " + System.identityHashCode(al));
+ addDatasetRef(vamsasSet.getDatasetId(), ds);
+ }
+ // set the dataset for the newly imported alignment.
+ if (al.getDataset() == null)
+ {
+ al.setDataset(ds);
+ }
+ }
+
+ /**
+ *
+ * @param vamsasSeq
+ * sequence definition to create/merge dataset sequence for
+ * @param ds
+ * dataset alignment
+ * @param dseqs
+ * vector to add new dataset sequence to
+ */
+ private void ensureJalviewDatasetSequence(Sequence vamsasSeq,
+ AlignmentI ds, Vector dseqs)
+ {
+ // JBP TODO: Check this is called for AlCodonFrames to support recovery of
+ // xRef Codon Maps
+ jalview.datamodel.Sequence sq = (jalview.datamodel.Sequence) seqRefIds
+ .get(vamsasSeq.getId());
+ jalview.datamodel.SequenceI dsq = null;
+ if (sq != null && sq.getDatasetSequence() != null)
+ {
+ dsq = sq.getDatasetSequence();
+ }
+
+ String sqid = vamsasSeq.getDsseqid();
+ if (dsq == null)
+ {
+ // need to create or add a new dataset sequence reference to this sequence
+ if (sqid != null)
+ {
+ dsq = (jalview.datamodel.SequenceI) seqRefIds.get(sqid);
+ }
+ // check again
+ if (dsq == null)
+ {
+ // make a new dataset sequence
+ dsq = sq.createDatasetSequence();
+ if (sqid == null)
+ {
+ // make up a new dataset reference for this sequence
+ sqid = seqHash(dsq);
+ }
+ dsq.setVamsasId(uniqueSetSuffix + sqid);
+ seqRefIds.put(sqid, dsq);
+ if (ds == null)
+ {
+ if (dseqs != null)
+ {
+ dseqs.addElement(dsq);
+ }
+ }
+ else
+ {
+ ds.addSequence(dsq);
+ }
+ }
+ else
+ {
+ if (sq != dsq)
+ { // make this dataset sequence sq's dataset sequence
+ sq.setDatasetSequence(dsq);
+ }
+ }
+ }
+ // TODO: refactor this as a merge dataset sequence function
+ // now check that sq (the dataset sequence) sequence really is the union of
+ // all references to it
+ // boolean pre = sq.getStart() < dsq.getStart();
+ // boolean post = sq.getEnd() > dsq.getEnd();
+ // if (pre || post)
+ if (sq != dsq)
+ {
+ StringBuffer sb = new StringBuffer();
+ String newres = jalview.analysis.AlignSeq.extractGaps(
+ jalview.util.Comparison.GapChars, sq.getSequenceAsString());
+ if (!newres.equalsIgnoreCase(dsq.getSequenceAsString())
+ && newres.length() > dsq.getLength())
+ {
+ // Update with the longer sequence.
+ synchronized (dsq)
+ {
+ /*
+ * if (pre) { sb.insert(0, newres .substring(0, dsq.getStart() -
+ * sq.getStart())); dsq.setStart(sq.getStart()); } if (post) {
+ * sb.append(newres.substring(newres.length() - sq.getEnd() -
+ * dsq.getEnd())); dsq.setEnd(sq.getEnd()); }
+ */
+ dsq.setSequence(sb.toString());
+ }
+ // TODO: merges will never happen if we 'know' we have the real dataset
+ // sequence - this should be detected when id==dssid
+ System.err.println("DEBUG Notice: Merged dataset sequence"); // ("
+ // + (pre ? "prepended" : "") + " "
+ // + (post ? "appended" : ""));
+ }
+ }
+ }
+
+ java.util.Hashtable datasetIds = null;
+
+ java.util.IdentityHashMap dataset2Ids = null;
+
+ private Alignment getDatasetFor(String datasetId)
+ {
+ if (datasetIds == null)
+ {
+ datasetIds = new Hashtable();
+ return null;
+ }
+ if (datasetIds.containsKey(datasetId))
+ {
+ return (Alignment) datasetIds.get(datasetId);
+ }
+ return null;
+ }
+
+ private void addDatasetRef(String datasetId, Alignment dataset)
+ {
+ if (datasetIds == null)
+ {
+ datasetIds = new Hashtable();
+ }
+ datasetIds.put(datasetId, dataset);
+ }
+
+ /**
+ * make a new dataset ID for this jalview dataset alignment
+ *
+ * @param dataset
+ * @return
+ */
+ private String getDatasetIdRef(jalview.datamodel.Alignment dataset)
+ {
+ if (dataset.getDataset() != null)
+ {
+ warn("Serious issue! Dataset Object passed to getDatasetIdRef is not a Jalview DATASET alignment...");
+ }
+ String datasetId = makeHashCode(dataset, null);
+ if (datasetId == null)
+ {
+ // make a new datasetId and record it
+ if (dataset2Ids == null)
+ {
+ dataset2Ids = new IdentityHashMap();
+ }
+ else
+ {
+ datasetId = (String) dataset2Ids.get(dataset);
+ }
+ if (datasetId == null)
+ {
+ datasetId = "ds" + dataset2Ids.size() + 1;
+ dataset2Ids.put(dataset, datasetId);
+ }
+ }
+ return datasetId;
+ }
+
+ private void addDBRefs(SequenceI datasetSequence, Sequence sequence)
+ {
+ for (int d = 0; d < sequence.getDBRefCount(); d++)
+ {
+ DBRef dr = sequence.getDBRef(d);
+ jalview.datamodel.DBRefEntry entry = new jalview.datamodel.DBRefEntry(
+ sequence.getDBRef(d).getSource(), sequence.getDBRef(d)
+ .getVersion(), sequence.getDBRef(d).getAccessionId());
+ if (dr.getMapping() != null)
+ {
+ entry.setMap(addMapping(dr.getMapping()));
+ }
+ datasetSequence.addDBRef(entry);
+ }
+ }
+
+ private jalview.datamodel.Mapping addMapping(Mapping m)
+ {
+ SequenceI dsto = null;
+ // Mapping m = dr.getMapping();
+ int fr[] = new int[m.getMapListFromCount() * 2];
+ Enumeration f = m.enumerateMapListFrom();
+ for (int _i = 0; f.hasMoreElements(); _i += 2)
+ {
+ MapListFrom mf = (MapListFrom) f.nextElement();
+ fr[_i] = mf.getStart();
+ fr[_i + 1] = mf.getEnd();
+ }
+ int fto[] = new int[m.getMapListToCount() * 2];
+ f = m.enumerateMapListTo();
+ for (int _i = 0; f.hasMoreElements(); _i += 2)
+ {
+ MapListTo mf = (MapListTo) f.nextElement();
+ fto[_i] = mf.getStart();
+ fto[_i + 1] = mf.getEnd();
+ }
+ jalview.datamodel.Mapping jmap = new jalview.datamodel.Mapping(dsto,
+ fr, fto, (int) m.getMapFromUnit(), (int) m.getMapToUnit());
+ if (m.getMappingChoice() != null)
+ {
+ MappingChoice mc = m.getMappingChoice();
+ if (mc.getDseqFor() != null)
+ {
+ String dsfor = "" + mc.getDseqFor();
+ if (seqRefIds.containsKey(dsfor))
+ {
+ /**
+ * recover from hash
+ */
+ jmap.setTo((SequenceI) seqRefIds.get(dsfor));
+ }
+ else
+ {
+ frefedSequence.add(new Object[]
+ { dsfor, jmap });
+ }
+ }
+ else
+ {
+ /**
+ * local sequence definition
+ */
+ Sequence ms = mc.getSequence();
+ jalview.datamodel.Sequence djs = null;
+ String sqid = ms.getDsseqid();
+ if (sqid != null && sqid.length() > 0)
+ {
+ /*
+ * recover dataset sequence
+ */
+ djs = (jalview.datamodel.Sequence) seqRefIds.get(sqid);
+ }
+ else
+ {
+ System.err
+ .println("Warning - making up dataset sequence id for DbRef sequence map reference");
+ sqid = ((Object) ms).toString(); // make up a new hascode for
+ // undefined dataset sequence hash
+ // (unlikely to happen)
+ }
+
+ if (djs == null)
+ {
+ /**
+ * make a new dataset sequence and add it to refIds hash
+ */
+ djs = new jalview.datamodel.Sequence(ms.getName(),
+ ms.getSequence());
+ djs.setStart(jmap.getMap().getToLowest());
+ djs.setEnd(jmap.getMap().getToHighest());
+ djs.setVamsasId(uniqueSetSuffix + sqid);
+ jmap.setTo(djs);
+ seqRefIds.put(sqid, djs);
+
+ }
+ jalview.bin.Cache.log.debug("about to recurse on addDBRefs.");
+ addDBRefs(djs, ms);
+
+ }
+ }
+ return (jmap);
+
+ }
+
+ public jalview.gui.AlignmentPanel copyAlignPanel(AlignmentPanel ap,
+ boolean keepSeqRefs)
+ {
+ initSeqRefs();
+ jalview.schemabinding.version2.JalviewModel jm = SaveState(ap, null,
+ null);
+
+ if (!keepSeqRefs)
+ {
+ clearSeqRefs();
+ jm.getJalviewModelSequence().getViewport(0).setSequenceSetId(null);
+ }
+ else
+ {
+ uniqueSetSuffix = "";
+ jm.getJalviewModelSequence().getViewport(0).setId(null); // we don't
+ // overwrite the
+ // view we just
+ // copied
+ }
+ if (this.frefedSequence == null)
+ {
+ frefedSequence = new Vector();
+ }
+
+ viewportsAdded = new Hashtable();
+
+ AlignFrame af = LoadFromObject(jm, null, false, null);
+ af.alignPanels.clear();
+ af.closeMenuItem_actionPerformed(true);
+
+ /*
+ * if(ap.av.getAlignment().getAlignmentAnnotation()!=null) { for(int i=0;
+ * i<ap.av.getAlignment().getAlignmentAnnotation().length; i++) {
+ * if(!ap.av.getAlignment().getAlignmentAnnotation()[i].autoCalculated) {
+ * af.alignPanel.av.getAlignment().getAlignmentAnnotation()[i] =
+ * ap.av.getAlignment().getAlignmentAnnotation()[i]; } } }
+ */
+
+ return af.alignPanel;
+ }
+
+ /**
+ * flag indicating if hashtables should be cleared on finalization TODO this
+ * flag may not be necessary
+ */
+ private final boolean _cleartables = true;
+
+ private Hashtable jvids2vobj;
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#finalize()
+ */
+ @Override
+ protected void finalize() throws Throwable
+ {
+ // really make sure we have no buried refs left.
+ if (_cleartables)
+ {
+ clearSeqRefs();
+ }
+ this.seqRefIds = null;
+ this.seqsToIds = null;
+ super.finalize();
+ }
+
+ private void warn(String msg)
+ {
+ warn(msg, null);
+ }
+
+ private void warn(String msg, Exception e)
+ {
+ if (Cache.log != null)
+ {
+ if (e != null)
+ {
+ Cache.log.warn(msg, e);
+ }
+ else
+ {
+ Cache.log.warn(msg);
+ }
+ }
+ else
+ {
+ System.err.println("Warning: " + msg);
+ if (e != null)
+ {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ private void debug(String string)
+ {
+ debug(string, null);
+ }
+
+ private void debug(String msg, Exception e)
+ {
+ if (Cache.log != null)
+ {
+ if (e != null)
+ {
+ Cache.log.debug(msg, e);
+ }
+ else
+ {
+ Cache.log.debug(msg);
+ }
+ }
+ else
+ {
+ System.err.println("Warning: " + msg);
+ if (e != null)
+ {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ /**
+ * set the object to ID mapping tables used to write/recover objects and XML
+ * ID strings for the jalview project. If external tables are provided then
+ * finalize and clearSeqRefs will not clear the tables when the Jalview2XML
+ * object goes out of scope. - also populates the datasetIds hashtable with
+ * alignment objects containing dataset sequences
+ *
+ * @param vobj2jv
+ * Map from ID strings to jalview datamodel
+ * @param jv2vobj
+ * Map from jalview datamodel to ID strings
+ *
+ *
+ */
+ public void setObjectMappingTables(Hashtable vobj2jv,
+ IdentityHashMap jv2vobj)
+ {
+ this.jv2vobj = jv2vobj;
+ this.vobj2jv = vobj2jv;
+ Iterator ds = jv2vobj.keySet().iterator();
+ String id;
+ while (ds.hasNext())
+ {
+ Object jvobj = ds.next();
+ id = jv2vobj.get(jvobj).toString();
+ if (jvobj instanceof jalview.datamodel.Alignment)
+ {
+ if (((jalview.datamodel.Alignment) jvobj).getDataset() == null)
+ {
+ addDatasetRef(id, (jalview.datamodel.Alignment) jvobj);
+ }
+ }
+ else if (jvobj instanceof jalview.datamodel.Sequence)
+ {
+ // register sequence object so the XML parser can recover it.
+ if (seqRefIds == null)
+ {
+ seqRefIds = new Hashtable();
+ }
+ if (seqsToIds == null)
+ {
+ seqsToIds = new IdentityHashMap();
+ }
+ seqRefIds.put(jv2vobj.get(jvobj).toString(), jvobj);
+ seqsToIds.put(jvobj, id);
+ }
+ else if (jvobj instanceof jalview.datamodel.AlignmentAnnotation)
+ {
+ if (annotationIds == null)
+ {
+ annotationIds = new Hashtable();
+ }
+ String anid;
+ annotationIds.put(anid = jv2vobj.get(jvobj).toString(), jvobj);
+ jalview.datamodel.AlignmentAnnotation jvann = (jalview.datamodel.AlignmentAnnotation) jvobj;
+ if (jvann.annotationId == null)
+ {
+ jvann.annotationId = anid;
+ }
+ if (!jvann.annotationId.equals(anid))
+ {
+ // TODO verify that this is the correct behaviour
+ this.warn("Overriding Annotation ID for " + anid
+ + " from different id : " + jvann.annotationId);
+ jvann.annotationId = anid;
+ }
+ }
+ else if (jvobj instanceof String)
+ {
+ if (jvids2vobj == null)
+ {
+ jvids2vobj = new Hashtable();
+ jvids2vobj.put(jvobj, jv2vobj.get(jvobj).toString());
+ }
+ }
+ else
+ Cache.log.debug("Ignoring " + jvobj.getClass() + " (ID = " + id);
+ }
+ }
+
+ /**
+ * set the uniqueSetSuffix used to prefix/suffix object IDs for jalview
+ * objects created from the project archive. If string is null (default for
+ * construction) then suffix will be set automatically.
+ *
+ * @param string
+ */
+ public void setUniqueSetSuffix(String string)
+ {
+ uniqueSetSuffix = string;
+
+ }
+
+ /**
+ * uses skipList2 as the skipList for skipping views on sequence sets
+ * associated with keys in the skipList
+ *
+ * @param skipList2
+ */
+ public void setSkipList(Hashtable skipList2)
+ {
+ skipList = skipList2;
+ }
+
+}