*/
public class Jalview2XML
{
-
- Hashtable seqRefIds = null;
+ /**
+ * create/return unique hash string for sq
+ * @param sq
+ * @return new or existing unique string for sq
+ */
+ String seqHash(SequenceI sq)
+ {
+ if (seqsToIds==null)
+ {
+ initSeqRefs();
+ }
+ if (seqsToIds.containsKey(sq))
+ {
+ return (String) seqsToIds.get(sq);
+ } else {
+ // create sequential key
+ String key = "sq"+(seqsToIds.size()+1);
+ seqsToIds.put(sq, key);
+ return key;
+ }
+ }
+ void clearSeqRefs()
+ {
+ seqRefIds.clear();
+ seqsToIds.clear();
+ }
+ void initSeqRefs()
+ {
+ if (seqsToIds==null)
+ {
+ seqsToIds = new IdentityHashMap();
+ }
+ if (seqRefIds==null)
+ {
+ seqRefIds = new Hashtable();
+ }
+ }
+ java.util.IdentityHashMap seqsToIds = null; // SequenceI->key resolution
+ java.util.Hashtable seqRefIds = null; // key->SequenceI resolution
Vector frefedSequence = null;
+ boolean raiseGUI = true; // whether errors are raised in dialog boxes or not
+ public Jalview2XML()
+ {
+ }
+ public Jalview2XML(boolean raiseGUI)
+ {
+ this.raiseGUI = raiseGUI;
+ }
public void resolveFrefedSequences()
{
//NOTE UTF-8 MUST BE USED FOR WRITING UNICODE CHARS
////////////////////////////////////////////////////
- PrintWriter out = new PrintWriter(new OutputStreamWriter(jout,
- "UTF-8"));
+ //NOTE ALSO new PrintWriter must be used for each new JarEntry
+ PrintWriter out = null;
Vector shortNames = new Vector();
{
AlignmentPanel apanel = (AlignmentPanel) af.alignPanels
.elementAt(ap);
+ String fileName = apSize == 1 ? shortName : ap + shortName;
+ if (!fileName.endsWith(".xml"))
+ {
+ fileName = fileName + ".xml";
+ }
- SaveState(apanel, apSize == 1 ? shortName : ap + shortName,
- jout, out);
+ SaveState(apanel, fileName, jout);
}
}
}
-
- out.close();
+ try { jout.flush(); } catch (Exception foo) {};
jout.close();
} catch (Exception ex)
{
+ //TODO: inform user of the problem - they need to know if their data was not saved !
ex.printStackTrace();
}
}
int ap, apSize = af.alignPanels.size();
FileOutputStream fos = new FileOutputStream(jarFile);
JarOutputStream jout = new JarOutputStream(fos);
- PrintWriter out = new PrintWriter(new OutputStreamWriter(jout,
- "UTF-8"));
for (ap = 0; ap < apSize; ap++)
{
AlignmentPanel apanel = (AlignmentPanel) af.alignPanels
.elementAt(ap);
-
- SaveState(apanel, apSize == 1 ? fileName : fileName + ap, jout, out);
+ String jfileName = apSize == 1 ? fileName : fileName + ap;
+ if (!jfileName.endsWith(".xml"))
+ {
+ jfileName = jfileName + ".xml";
+ }
+ SaveState(apanel, jfileName, jout);
}
- out.close();
+ try { jout.flush(); } catch (Exception foo) {};
jout.close();
return true;
} catch (Exception ex)
}
/**
- * DOCUMENT ME!
+ * create a JalviewModel from an algnment view and marshall it
+ * to a JarOutputStream
*
- * @param af DOCUMENT ME!
- * @param timeStamp DOCUMENT ME!
- * @param fileName DOCUMENT ME!
- * @param jout DOCUMENT ME!
- * @param out DOCUMENT ME!
+ * @param ap panel to create jalview model for
+ * @param fileName name of alignment panel written to output stream
+ * @param jout jar output stream
+ * @param out jar entry name
*/
public JalviewModel SaveState(AlignmentPanel ap, String fileName,
- JarOutputStream jout, PrintWriter out)
+ JarOutputStream jout)
{
- if (seqRefIds == null)
- {
- seqRefIds = new Hashtable();
- }
-
+ initSeqRefs();
+
Vector userColours = new Vector();
AlignViewport av = ap.av;
JSeq jseq;
//SAVE SEQUENCES
- int id = 0;
+ String id = "";
jalview.datamodel.SequenceI jds;
for (int i = 0; i < jal.getHeight(); i++)
{
jds = jal.getSequenceAt(i);
- id = jds.hashCode();
-
- if (seqRefIds.get(id + "") != null)
- {
-
+ id = seqHash(jds);
+
+ if (seqRefIds.get(id) != null)
+ {
+ // This happens for two reasons: 1. multiple views are being serialised. 2. the hashCode has collided with another sequence's code. This DOES HAPPEN! (PF00072.15.stk does this)
+ // JBPNote: Uncomment to debug writing out of files that do not read back in due to ArrayOutOfBoundExceptions.
+ //System.err.println("vamsasSeq backref: "+id+"");
+ //System.err.println(jds.getName()+" "+jds.getStart()+"-"+jds.getEnd()+" "+jds.getSequenceAsString());
+ //System.err.println("Hashcode: "+seqHash(jds));
+ //SequenceI rsq = (SequenceI) seqRefIds.get(id + "");
+ //System.err.println(rsq.getName()+" "+rsq.getStart()+"-"+rsq.getEnd()+" "+rsq.getSequenceAsString());
+ //System.err.println("Hashcode: "+seqHash(rsq));
}
else
{
vamsasSeq = createVamsasSequence(id, jds);
vamsasSet.addSequence(vamsasSeq);
- seqRefIds.put(id + "", jal.getSequenceAt(i));
+ seqRefIds.put(id, jds);
}
jseq = new JSeq();
jseq.setEnd(jds.getEnd());
jseq.setColour(av.getSequenceColour(jds).getRGB());
- jseq.setId(id);
+ jseq.setId(id); // jseq id should be a string not a number
if (av.hasHiddenRows)
{
DataOutputStream dout = new DataOutputStream(jout);
dout.write(data, 0, data.length);
+ dout.flush();
jout.closeEntry();
}
} catch (Exception ex)
{
AlcodonFrame alc = new AlcodonFrame();
vamsasSet.addAlcodonFrame(alc);
- for (int p = 0; p < jac[i].aaWidth; i++)
+ for (int p = 0; p < jac[i].aaWidth; p++)
{
Alcodon cmap = new Alcodon();
cmap.setPos1(jac[i].codons[p][0]);
{
jalview.datamodel.Sequence seq = (jalview.datamodel.Sequence) sg
.getSequenceAt(s);
- groups[i].addSeq(seq.hashCode());
+ groups[i].addSeq(seqHash(seq));
}
}
object.setJalviewModelSequence(jms);
object.getVamsasModel().addSequenceSet(vamsasSet);
- if (out != null)
+ if (jout!=null && fileName!=null)
{
- //We may not want to right the object to disk,
+ //We may not want to write the object to disk,
//eg we can copy the alignViewport to a new view object
//using save and then load
try
{
- if (!fileName.endsWith(".xml"))
- {
- fileName = fileName + ".xml";
- }
-
JarEntry entry = new JarEntry(fileName);
jout.putNextEntry(entry);
-
- object.marshal(out);
+ PrintWriter pout = new PrintWriter(new OutputStreamWriter(jout,
+ "UTF-8"));
+ org.exolab.castor.xml.Marshaller marshaller = new org.exolab.castor.xml.Marshaller(pout);
+ marshaller.marshal(object);
+ pout.flush();
+ jout.closeEntry();
} catch (Exception ex)
{
+ // TODO: raise error in GUI if marshalling failed.
ex.printStackTrace();
}
}
return object;
}
- private Sequence createVamsasSequence(int id, SequenceI jds)
+ private Sequence createVamsasSequence(String id, SequenceI jds)
{
return createVamsasSequence(true, id, jds, null);
}
- private Sequence createVamsasSequence(boolean recurse, int id,
+ private Sequence createVamsasSequence(boolean recurse, String id,
SequenceI jds, SequenceI parentseq)
{
Sequence vamsasSeq = new Sequence();
- vamsasSeq.setId(id + "");
+ vamsasSeq.setId(id);
vamsasSeq.setName(jds.getName());
vamsasSeq.setSequence(jds.getSequenceAsString());
vamsasSeq.setDescription(jds.getDescription());
jalview.datamodel.DBRefEntry[] dbrefs = null;
if (jds.getDatasetSequence() != null)
{
- vamsasSeq.setDsseqid(jds.getDatasetSequence().hashCode() + "");
+ vamsasSeq.setDsseqid(seqHash(jds.getDatasetSequence()));
if (jds.getDatasetSequence().getDBRef() != null)
{
dbrefs = jds.getDatasetSequence().getDBRef();
}
else
{
+ vamsasSeq.setDsseqid(id); // so we can tell which sequences really are dataset sequences only
dbrefs = jds.getDBRef();
}
- if (jds.getDBRef() != null)
+ if (dbrefs != null)
{
for (int d = 0; d < dbrefs.length; d++)
{
&& (parentseq != jmp.getTo() || parentseq
.getDatasetSequence() != jmp.getTo()))
{
- mpc.setSequence(createVamsasSequence(false, jmp.getTo()
- .hashCode(), jmp.getTo(), jds));
+ mpc.setSequence(createVamsasSequence(false, seqHash(jmp.getTo())
+ , jmp.getTo(), jds));
}
else
{
- long jmpid = 0;
+ String jmpid = "";
SequenceI ps = null;
if (parentseq != jmp.getTo()
&& parentseq.getDatasetSequence() != jmp.getTo())
{
// chaining dbref rather than a handshaking one
- jmpid = (ps = jmp.getTo()).hashCode();
+ jmpid = seqHash(ps = jmp.getTo());
}
else
{
- jmpid = (ps = parentseq).hashCode();
+ jmpid = seqHash(ps = parentseq);
}
- mpc.setDseqFor("" + jmpid);
+ mpc.setDseqFor(jmpid);
if (!seqRefIds.containsKey(mpc.getDseqFor()))
{
jalview.bin.Cache.log.debug("creatign new DseqFor ID");
+ ex + "\n");
} catch (Exception ex)
{
+ System.err.println("Parsing as Jalview Version 2 file failed.");
+ ex.printStackTrace(System.err);
+
//Is Version 1 Jar file?
- af = new Jalview2XML_V1().LoadJalviewAlign(file);
+ try {
+ af = new Jalview2XML_V1(raiseGUI).LoadJalviewAlign(file);
+ } 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");
if (errorMessage != null)
{
final String finalErrorMessage = errorMessage;
- javax.swing.SwingUtilities.invokeLater(new Runnable()
- {
- public void run()
+ if (raiseGUI)
+ {
+ javax.swing.SwingUtilities.invokeLater(new Runnable()
+ {
+ public void run()
{
JOptionPane.showInternalMessageDialog(Desktop.desktop,
finalErrorMessage, "Error loading Jalview file",
JOptionPane.WARNING_MESSAGE);
}
});
+ } else {
+ System.err.println("Problem loading Jalview file: "+errorMessage);
+ }
}
return af;
{
out.println(data);
}
+ try { out.flush(); } catch (Exception foo) {};
out.close();
alreadyLoadedPDB.put(pdbId, outFile.getAbsolutePath());
boolean multipleView = false;
JSeq[] JSEQ = object.getJalviewModelSequence().getJSeq();
+ int vi=0; // counter in vamsasSeq array
for (int i = 0; i < JSEQ.length; i++)
{
String seqId = JSEQ[i].getId() + "";
}
else
{
- jseq = new jalview.datamodel.Sequence(vamsasSeq[i].getName(),
- vamsasSeq[i].getSequence());
- jseq.setDescription(vamsasSeq[i].getDescription());
+ jseq = new jalview.datamodel.Sequence(vamsasSeq[vi].getName(),
+ vamsasSeq[vi].getSequence());
+ jseq.setDescription(vamsasSeq[vi].getDescription());
jseq.setStart(JSEQ[i].getStart());
jseq.setEnd(JSEQ[i].getEnd());
jseq.setVamsasId(uniqueSetSuffix + seqId);
- seqRefIds.put(vamsasSeq[i].getId(), jseq);
+ seqRefIds.put(vamsasSeq[vi].getId()+"", jseq);
tmpseqs.add(jseq);
+ vi++;
}
if (JSEQ[i].getHidden())
{
// older jalview projects do not have a dataset id.
al.setDataset(null);
- // addDatasetRef(al.getDataset());
}
else
{
al.getSequenceAt(i).getDatasetSequence().addSequenceFeature(sf);
}
}
-
+ if (vamsasSeq[i].getDBRefCount() > 0)
+ {
+ addDBRefs(al.getSequenceAt(i).getDatasetSequence(), vamsasSeq[i]);
+ }
if (JSEQ[i].getPdbidsCount() > 0)
{
Pdbids[] ids = JSEQ[i].getPdbids();
al.getSequenceAt(i).getDatasetSequence().addPDBId(entry);
}
}
- if (vamsasSeq[i].getDBRefCount() > 0)
- {
- addDBRefs(al.getSequenceAt(i).getDatasetSequence(), vamsasSeq[i]);
- }
}
}
.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[ae[aa].getPosition()].colour = new java.awt.Color(ae[aa]
.getColour());
}
int height = ids[p].getStructureState(s).getHeight();
java.awt.Component comp = null;
-
- JInternalFrame[] frames = Desktop.desktop.getAllFrames();
+
+ JInternalFrame[] frames = null;
+ do {
+ try {
+ frames = Desktop.desktop.getAllFrames();
+ }
+ catch (ArrayIndexOutOfBoundsException e)
+ {
+ // occasional No such child exceptions are thrown here...
+ frames = null;
+ try {
+ Thread.sleep(10);
+ } catch (Exception f) {};
+ }
+ } while (frames==null);
for (int f = 0; f < frames.length; f++)
{
if (frames[f] instanceof AppJmol)
for (int i = 0, iSize = vamsasSet.getSequenceCount(); i < iSize; i++)
{
Sequence vamsasSeq = vamsasSet.getSequence(i);
- jalview.datamodel.Sequence sq = null;
- String sqid = vamsasSeq.getDsseqid();
+ 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);
+ 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)
+ {
+ jalview.datamodel.Sequence sq = (jalview.datamodel.Sequence) seqRefIds.get(vamsasSeq.getId());
+ jalview.datamodel.SequenceI dsq = null;
+ if (sq!=null && sq.getDatasetSequence()!=null)
+ {
+ dsq = (jalview.datamodel.SequenceI) 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)
{
- sq = (jalview.datamodel.Sequence) seqRefIds.get(vamsasSeq
- .getDsseqid());
+ dsq = (jalview.datamodel.SequenceI) seqRefIds.get(sqid);
}
- if (sq == null)
+ // check again
+ if (dsq == null)
{
- sq = (jalview.datamodel.Sequence) seqRefIds.get(vamsasSeq.getId());
- jalview.datamodel.SequenceI dsq = sq.createDatasetSequence();
+ // make a new dataset sequence
+ dsq = sq.createDatasetSequence();
if (sqid == null)
{
// make up a new dataset reference for this sequence
- sqid = "" + dsq.hashCode();
+ sqid = seqHash(dsq);
}
- ((SequenceI) dsq).setVamsasId(uniqueSetSuffix + sqid);
+ dsq.setVamsasId(uniqueSetSuffix + sqid);
seqRefIds.put(sqid, dsq);
if (ds == null)
{
- dseqs.addElement(dsq);
+ 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 is a low-level sequence operation - effectively merging one dataset sequence into another.
- // check that dataset sequence really is the union of all references to it
- boolean pre = sq.getStart() < sq.getDatasetSequence().getStart();
- boolean post = sq.getEnd() > sq.getDatasetSequence().getEnd();
- if (pre || post)
+ }
+ // 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())
{
- SequenceI dsq = sq.getDatasetSequence();
- StringBuffer sb = new StringBuffer();
- String newres = jalview.analysis.AlignSeq.extractGaps(
- jalview.util.Comparison.GapChars, sq.getSequenceAsString());
+ // Update with the longer sequence.
synchronized (dsq)
{
- sb.append(dsq.getSequence());
- 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());
+ /*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" : ""));
+ .println("DEBUG Notice: Merged dataset sequence"); // ("
+ // + (pre ? "prepended" : "") + " "
+ //+ (post ? "appended" : ""));
}
}
- // create a new dataset
- if (ds == null)
- {
- SequenceI[] dsseqs = new SequenceI[dseqs.size()];
- dseqs.copyInto(dsseqs);
- ds = new jalview.datamodel.Alignment(dsseqs);
- addDatasetRef(vamsasSet.getDatasetId(), ds);
- }
- // set the dataset for the newly imported alignment.
- if (al.getDataset() == null)
- {
- al.setDataset(ds);
- }
}
java.util.Hashtable datasetIds = null;
else
{
/**
- * make a new sequence and add it to refIds hash
+ * local sequence definition
*/
Sequence ms = mc.getSequence();
- jalview.datamodel.Sequence djs = new jalview.datamodel.Sequence(ms
+ 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 + ms.getId());
- jmap.setTo(djs);
- seqRefIds.put(ms.getId(), djs);
+ 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)
{
- jalview.schemabinding.version2.JalviewModel jm = SaveState(ap, null,
- null, null);
+ jalview.schemabinding.version2.JalviewModel jm =
+ SaveState(ap, null, null);
if (!keepSeqRefs)
{
- seqRefIds.clear();
+ clearSeqRefs();
jm.getJalviewModelSequence().getViewport(0).setSequenceSetId(null);
}
else
return af.alignPanel;
}
+ /* (non-Javadoc)
+ * @see java.lang.Object#finalize()
+ */
+ protected void finalize() throws Throwable
+ {
+ // really make sure we have no buried refs left.
+ clearSeqRefs();
+ this.seqRefIds = null;
+ this.seqsToIds = null;
+ super.finalize();
+ }
+
}