X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fgui%2FJalview2XML.java;h=1c90889d9ac232a6e93ffdfc1e6e68fa71094748;hb=f40e44c9db0a689f2df188cf07801b035096c1b1;hp=0ebc8045d9e7c3f49fb5cbd5c9236b27495c4ffd;hpb=ced9774e6ac645ef1b231e560fcf5f70a4e44263;p=jalview.git diff --git a/src/jalview/gui/Jalview2XML.java b/src/jalview/gui/Jalview2XML.java index 0ebc804..1c90889 100644 --- a/src/jalview/gui/Jalview2XML.java +++ b/src/jalview/gui/Jalview2XML.java @@ -20,45 +20,9 @@ */ package jalview.gui; -import java.awt.Rectangle; -import java.io.BufferedReader; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStreamWriter; -import java.io.PrintWriter; -import java.lang.reflect.InvocationTargetException; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.ArrayList; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Hashtable; -import java.util.IdentityHashMap; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.StringTokenizer; -import java.util.Vector; -import java.util.jar.JarEntry; -import java.util.jar.JarInputStream; -import java.util.jar.JarOutputStream; - -import javax.swing.JInternalFrame; -import javax.swing.JOptionPane; -import javax.swing.SwingUtilities; - -import org.exolab.castor.xml.Marshaller; -import org.exolab.castor.xml.Unmarshaller; - +import jalview.analysis.Conservation; +import jalview.api.FeatureColourI; +import jalview.api.ViewStyleI; import jalview.api.structures.JalviewStructureDisplayI; import jalview.bin.Cache; import jalview.datamodel.AlignedCodonFrame; @@ -109,7 +73,7 @@ import jalview.schemabinding.version2.Viewport; import jalview.schemes.AnnotationColourGradient; import jalview.schemes.ColourSchemeI; import jalview.schemes.ColourSchemeProperty; -import jalview.schemes.GraduatedColor; +import jalview.schemes.FeatureColour; import jalview.schemes.ResidueColourScheme; import jalview.schemes.ResidueProperties; import jalview.schemes.UserColourScheme; @@ -117,6 +81,7 @@ import jalview.structure.StructureSelectionManager; import jalview.structures.models.AAStructureBindingModel; import jalview.util.MessageManager; import jalview.util.Platform; +import jalview.util.StringUtils; import jalview.util.jarInputStreamProvider; import jalview.viewmodel.AlignmentViewport; import jalview.viewmodel.seqfeatures.FeatureRendererSettings; @@ -128,6 +93,46 @@ import jalview.ws.params.ArgumentI; import jalview.ws.params.AutoCalcSetting; import jalview.ws.params.WsParamSetI; +import java.awt.Color; +import java.awt.Rectangle; +import java.io.BufferedReader; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.lang.reflect.InvocationTargetException; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Hashtable; +import java.util.IdentityHashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.Vector; +import java.util.jar.JarEntry; +import java.util.jar.JarInputStream; +import java.util.jar.JarOutputStream; + +import javax.swing.JInternalFrame; +import javax.swing.JOptionPane; +import javax.swing.SwingUtilities; + +import org.exolab.castor.xml.Marshaller; +import org.exolab.castor.xml.Unmarshaller; + /** * Write out the current jalview desktop state as a Jalview XML stream. * @@ -162,7 +167,9 @@ public class Jalview2XML */ Map seqRefIds = null; - Vector frefedSequence = null; + Map incompleteSeqs = null; + + List frefedSequence = null; boolean raiseGUI = true; // whether errors are raised in dialog boxes or not @@ -217,6 +224,10 @@ public class Jalview2XML { seqsToIds.clear(); } + if (incompleteSeqs != null) + { + incompleteSeqs.clear(); + } // seqRefIds = null; // seqsToIds = null; } @@ -239,6 +250,14 @@ public class Jalview2XML { seqRefIds = new HashMap(); } + if (incompleteSeqs == null) + { + incompleteSeqs = new HashMap(); + } + if (frefedSequence == null) + { + frefedSequence = new ArrayList(); + } } public Jalview2XML() @@ -250,78 +269,185 @@ public class Jalview2XML this.raiseGUI = raiseGUI; } + /** + * base class for resolving forward references to sequences by their ID + * + * @author jprocter + * + */ + abstract class SeqFref + { + String sref; + + String type; + + public SeqFref(String _sref, String type) + { + sref = _sref; + this.type = type; + } + + public String getSref() + { + return sref; + } + + public SequenceI getSrefSeq() + { + return seqRefIds.get(sref); + } + + public boolean isResolvable() + { + return seqRefIds.get(sref) != null; + } + + public SequenceI getSrefDatasetSeq() + { + SequenceI sq = seqRefIds.get(sref); + if (sq != null) + { + while (sq.getDatasetSequence() != null) + { + sq = sq.getDatasetSequence(); + } + } + return sq; + } + + /** + * @return true if the forward reference was fully resolved + */ + abstract boolean resolve(); + + @Override + public String toString() + { + return type + " reference to " + sref; + } + } + + /** + * create forward reference for a mapping + * + * @param sref + * @param _jmap + * @return + */ + public SeqFref newMappingRef(final String sref, + final jalview.datamodel.Mapping _jmap) + { + SeqFref fref = new SeqFref(sref, "Mapping") + { + public jalview.datamodel.Mapping jmap = _jmap; + + @Override + boolean resolve() + { + SequenceI seq = getSrefDatasetSeq(); + if (seq == null) + { + return false; + } + jmap.setTo(seq); + return true; + } + }; + return fref; + } + + public SeqFref newAlcodMapRef(final String sref, + final AlignedCodonFrame _cf, final jalview.datamodel.Mapping _jmap) + { + + SeqFref fref = new SeqFref(sref, "Codon Frame") + { + AlignedCodonFrame cf = _cf; + + public jalview.datamodel.Mapping mp = _jmap; + + @Override + public boolean isResolvable() + { + return super.isResolvable() && mp.getTo() != null; + }; + + @Override + boolean resolve() + { + SequenceI seq = getSrefDatasetSeq(); + if (seq == null) + { + return false; + } + cf.addMap(seq, mp.getTo(), mp.getMap()); + return true; + } + }; + return fref; + } + public void resolveFrefedSequences() { - if (frefedSequence.size() > 0) + Iterator nextFref = frefedSequence.iterator(); + int toresolve = frefedSequence.size(); + int unresolved = 0, failedtoresolve = 0; + while (nextFref.hasNext()) { - int r = 0, rSize = frefedSequence.size(); - while (r < rSize) + SeqFref ref = nextFref.next(); + if (ref.isResolvable()) { - Object[] ref = (Object[]) frefedSequence.elementAt(r); - if (ref != null) + try { - String sref = (String) ref[0]; - if (seqRefIds.containsKey(sref)) + if (ref.resolve()) { - if (ref[1] instanceof jalview.datamodel.Mapping) - { - SequenceI seq = seqRefIds.get(sref); - while (seq.getDatasetSequence() != null) - { - seq = seq.getDatasetSequence(); - } - ((jalview.datamodel.Mapping) ref[1]).setTo(seq); - } - else - { - if (ref[1] instanceof jalview.datamodel.AlignedCodonFrame) - { - SequenceI seq = seqRefIds.get(sref); - while (seq.getDatasetSequence() != null) - { - seq = seq.getDatasetSequence(); - } - if (ref[2] != null - && ref[2] instanceof jalview.datamodel.Mapping) - { - jalview.datamodel.Mapping mp = (jalview.datamodel.Mapping) ref[2]; - ((jalview.datamodel.AlignedCodonFrame) ref[1]).addMap( - seq, mp.getTo(), mp.getMap()); - } - else - { - System.err - .println("IMPLEMENTATION ERROR: Unimplemented forward sequence references for AlcodonFrames involving " - + ref[2].getClass() + " type objects."); - } - } - else - { - System.err - .println("IMPLEMENTATION ERROR: Unimplemented forward sequence references for " - + ref[1].getClass() + " type objects."); - } - } - frefedSequence.remove(r); - rSize--; + nextFref.remove(); } else { - System.err - .println("IMPLEMENTATION WARNING: Unresolved forward reference for hash string " - + ref[0] - + " with objecttype " - + ref[1].getClass()); - r++; + failedtoresolve++; } + } catch (Exception x) + { + System.err + .println("IMPLEMENTATION ERROR: Failed to resolve forward reference for sequence " + + ref.getSref()); + x.printStackTrace(); + failedtoresolve++; } - else + } + else + { + unresolved++; + } + } + if (unresolved > 0) + { + System.err.println("Jalview Project Import: There were " + unresolved + + " forward references left unresolved on the stack."); + } + if (failedtoresolve > 0) + { + System.err.println("SERIOUS! " + failedtoresolve + + " resolvable forward references failed to resolve."); + } + if (incompleteSeqs != null && incompleteSeqs.size() > 0) + { + System.err.println("Jalview Project Import: There are " + + incompleteSeqs.size() + + " sequences which may have incomplete metadata."); + if (incompleteSeqs.size() < 10) + { + for (SequenceI s : incompleteSeqs.values()) { - // empty reference - frefedSequence.remove(r); - rSize--; + System.err.println(s.toString()); } } + else + { + System.err + .println("Too many to report. Skipping output of incomplete sequences."); + } } } @@ -393,7 +519,20 @@ public class Jalview2XML { return; } + saveAllFrames(Arrays.asList(frames), jout); + } + /** + * core method for storing state for a set of AlignFrames. + * + * @param frames + * - frames involving all data to be exported (including containing + * splitframes) + * @param jout + * - project output stream + */ + private void saveAllFrames(List frames, JarOutputStream jout) + { Hashtable dsses = new Hashtable(); /* @@ -413,9 +552,9 @@ public class Jalview2XML List viewIds = new ArrayList(); // REVERSE ORDER - for (int i = frames.length - 1; i > -1; i--) + for (int i = frames.size() - 1; i > -1; i--) { - AlignFrame af = frames[i]; + AlignFrame af = frames.get(i); // skip ? if (skipList != null && skipList @@ -518,30 +657,20 @@ public class Jalview2XML { try { - int ap = 0; - int apSize = af.alignPanels.size(); FileOutputStream fos = new FileOutputStream(jarFile); JarOutputStream jout = new JarOutputStream(fos); - Hashtable dsses = new Hashtable(); - List viewIds = new ArrayList(); + List frames = new ArrayList(); - for (AlignmentPanel apanel : af.alignPanels) + // resolve splitframes + if (af.getViewport().getCodingComplement() != null) { - String jfileName = apSize == 1 ? fileName : fileName + ap; - ap++; - if (!jfileName.endsWith(".xml")) - { - jfileName = jfileName + ".xml"; - } - saveState(apanel, jfileName, jout, viewIds); - String dssid = getDatasetIdRef(af.getViewport().getAlignment() - .getDataset()); - if (!dsses.containsKey(dssid)) - { - dsses.put(dssid, af); - } + frames = ((SplitFrame) af.getSplitViewContainer()).getAlignFrames(); + } + else + { + frames.add(af); } - writeDatasetFor(dsses, fileName, jout); + saveAllFrames(frames, jout); try { jout.flush(); @@ -632,11 +761,15 @@ public class Jalview2XML object.setVersion(jalview.bin.Cache.getDefault("VERSION", "Development Build")); - jalview.datamodel.AlignmentI jal = av.getAlignment(); + /** + * rjal is full height alignment, jal is actual alignment with full metadata + * but excludes hidden sequences. + */ + jalview.datamodel.AlignmentI rjal = av.getAlignment(), jal = rjal; if (av.hasHiddenRows()) { - jal = jal.getHiddenSequences().getFullAlignment(); + rjal = jal.getHiddenSequences().getFullAlignment(); } SequenceSet vamsasSet = new SequenceSet(); @@ -653,6 +786,7 @@ public class Jalview2XML { // switch jal and the dataset jal = jal.getDataset(); + rjal = jal; } } if (jal.getProperties() != null) @@ -670,39 +804,42 @@ public class Jalview2XML JSeq jseq; Set calcIdSet = new HashSet(); - + // record the set of vamsas sequence XML POJO we create. + HashMap vamsasSetIds = new HashMap(); // SAVE SEQUENCES - for (int i = 0; i < jal.getHeight(); i++) + for (final SequenceI jds : rjal.getSequences()) { - final SequenceI jds = jal.getSequenceAt(i); final SequenceI jdatasq = jds.getDatasetSequence() == null ? jds - : jds - .getDatasetSequence(); + : jds.getDatasetSequence(); String 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, jds); + if (vamsasSetIds.get(id) == null) + { + if (seqRefIds.get(id) != null && !storeDS) + { + // 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); + vamsasSetIds.put(id, vamsasSeq); + seqRefIds.put(id, jds); + } } - jseq = new JSeq(); jseq.setStart(jds.getStart()); jseq.setEnd(jds.getEnd()); @@ -714,30 +851,36 @@ public class Jalview2XML // Store any sequences this sequence represents if (av.hasHiddenRows()) { + // use rjal, contains the full height alignment jseq.setHidden(av.getAlignment().getHiddenSequences() .isHidden(jds)); - if (av.isHiddenRepSequence(jal.getSequenceAt(i))) + if (av.isHiddenRepSequence(jds)) { jalview.datamodel.SequenceI[] reps = av - .getRepresentedSequences(jal.getSequenceAt(i)) - .getSequencesInOrder(jal); + .getRepresentedSequences(jds).getSequencesInOrder(rjal); for (int h = 0; h < reps.length; h++) { - if (reps[h] != jal.getSequenceAt(i)) + if (reps[h] != jds) { - jseq.addHiddenSequences(jal.findIndex(reps[h])); + jseq.addHiddenSequences(rjal.findIndex(reps[h])); } } } } + // mark sequence as reference - if it is the reference for this view + if (jal.hasSeqrep()) + { + jseq.setViewreference(jds == jal.getSeqrep()); + } } + // TODO: omit sequence features from each alignment view's XML dump if we + // are storing dataset if (jds.getSequenceFeatures() != null) { - jalview.datamodel.SequenceFeature[] sf = jds - .getSequenceFeatures(); + jalview.datamodel.SequenceFeature[] sf = jds.getSequenceFeatures(); int index = 0; while (index < sf.length) { @@ -762,10 +905,11 @@ public class Jalview2XML if (sf[index].otherDetails != null) { String key; - Enumeration keys = sf[index].otherDetails.keys(); - while (keys.hasMoreElements()) + Iterator keys = sf[index].otherDetails.keySet() + .iterator(); + while (keys.hasNext()) { - key = keys.nextElement().toString(); + key = keys.next(); OtherData keyValue = new OtherData(); keyValue.setKey(key); keyValue.setValue(sf[index].otherDetails.get(key).toString()); @@ -778,9 +922,9 @@ public class Jalview2XML } } - if (jdatasq.getPDBId() != null) + if (jdatasq.getAllPDBEntries() != null) { - Enumeration en = jdatasq.getPDBId().elements(); + Enumeration en = jdatasq.getAllPDBEntries().elements(); while (en.hasMoreElements()) { Pdbids pdb = new Pdbids(); @@ -848,17 +992,16 @@ public class Jalview2XML } } - if (entry.getProperty() != null && !entry.getProperty().isEmpty()) + Enumeration props = entry.getProperties(); + if (props.hasMoreElements()) { PdbentryItem item = new PdbentryItem(); - Hashtable properties = entry.getProperty(); - Enumeration en2 = properties.keys(); - while (en2.hasMoreElements()) + while (props.hasMoreElements()) { Property prop = new Property(); - String key = en2.nextElement().toString(); + String key = props.nextElement(); prop.setName(key); - prop.setValue(properties.get(key).toString()); + prop.setValue(entry.getProperty(key).toString()); item.addProperty(prop); } pdb.addPdbentryItem(item); @@ -878,16 +1021,17 @@ public class Jalview2XML jal = av.getAlignment(); } // SAVE MAPPINGS - if (jal.getCodonFrames() != null) + // FOR DATASET + if (storeDS && jal.getCodonFrames() != null) { - Set jac = jal.getCodonFrames(); + List jac = jal.getCodonFrames(); for (AlignedCodonFrame acf : jac) { AlcodonFrame alc = new AlcodonFrame(); - vamsasSet.addAlcodonFrame(alc); if (acf.getProtMappings() != null && acf.getProtMappings().length > 0) { + boolean hasMap = false; SequenceI[] dnas = acf.getdnaSeqs(); jalview.datamodel.Mapping[] pmaps = acf.getProtMappings(); for (int m = 0; m < pmaps.length; m++) @@ -897,39 +1041,44 @@ public class Jalview2XML alcmap.setMapping(createVamsasMapping(pmaps[m], dnas[m], null, false)); alc.addAlcodMap(alcmap); + hasMap = true; + } + if (hasMap) + { + vamsasSet.addAlcodonFrame(alc); } } - -// { -// AlcodonFrame alc = new AlcodonFrame(); -// vamsasSet.addAlcodonFrame(alc); -// for (int p = 0; p < acf.aaWidth; p++) -// { -// Alcodon cmap = new Alcodon(); -// if (acf.codons[p] != null) -// { -// // Null codons indicate a gapped column in the translated peptide -// // alignment. -// cmap.setPos1(acf.codons[p][0]); -// cmap.setPos2(acf.codons[p][1]); -// cmap.setPos3(acf.codons[p][2]); -// } -// alc.addAlcodon(cmap); -// } -// if (acf.getProtMappings() != null -// && acf.getProtMappings().length > 0) -// { -// SequenceI[] dnas = acf.getdnaSeqs(); -// jalview.datamodel.Mapping[] pmaps = acf.getProtMappings(); -// for (int m = 0; m < pmaps.length; m++) -// { -// AlcodMap alcmap = new AlcodMap(); -// alcmap.setDnasq(seqHash(dnas[m])); -// alcmap.setMapping(createVamsasMapping(pmaps[m], dnas[m], null, -// false)); -// alc.addAlcodMap(alcmap); -// } -// } + // TODO: delete this ? dead code from 2.8.3->2.9 ? + // { + // AlcodonFrame alc = new AlcodonFrame(); + // vamsasSet.addAlcodonFrame(alc); + // for (int p = 0; p < acf.aaWidth; p++) + // { + // Alcodon cmap = new Alcodon(); + // if (acf.codons[p] != null) + // { + // // Null codons indicate a gapped column in the translated peptide + // // alignment. + // cmap.setPos1(acf.codons[p][0]); + // cmap.setPos2(acf.codons[p][1]); + // cmap.setPos3(acf.codons[p][2]); + // } + // alc.addAlcodon(cmap); + // } + // if (acf.getProtMappings() != null + // && acf.getProtMappings().length > 0) + // { + // SequenceI[] dnas = acf.getdnaSeqs(); + // jalview.datamodel.Mapping[] pmaps = acf.getProtMappings(); + // for (int m = 0; m < pmaps.length; m++) + // { + // AlcodMap alcmap = new AlcodMap(); + // alcmap.setDnasq(seqHash(dnas[m])); + // alcmap.setMapping(createVamsasMapping(pmaps[m], dnas[m], null, + // false)); + // alc.addAlcodMap(alcmap); + // } + // } } } @@ -1032,13 +1181,11 @@ public class Jalview2XML if (sg.cs instanceof jalview.schemes.UserColourScheme) { - jGroup.setColour(setUserColourScheme(sg.cs, userColours, - jms)); + jGroup.setColour(setUserColourScheme(sg.cs, userColours, jms)); } else { - jGroup - .setColour(ColourSchemeProperty.getColourName(sg.cs)); + jGroup.setColour(ColourSchemeProperty.getColourName(sg.cs)); } } else if (sg.cs instanceof jalview.schemes.AnnotationColourGradient) @@ -1050,8 +1197,7 @@ public class Jalview2XML } else if (sg.cs instanceof jalview.schemes.UserColourScheme) { - jGroup - .setColour(setUserColourScheme(sg.cs, userColours, jms)); + jGroup.setColour(setUserColourScheme(sg.cs, userColours, jms)); } else { @@ -1096,15 +1242,26 @@ public class Jalview2XML view.setViewName(av.viewName); view.setGatheredViews(av.isGatherViewsHere()); - Rectangle position = ap.av.getExplodedGeometry(); - if (position == null) + Rectangle size = ap.av.getExplodedGeometry(); + Rectangle position = size; + if (size == null) { - position = ap.alignFrame.getBounds(); + size = ap.alignFrame.getBounds(); + if (av.getCodingComplement() != null) + { + position = ((SplitFrame) ap.alignFrame.getSplitViewContainer()) + .getBounds(); + } + else + { + position = size; + } } view.setXpos(position.x); view.setYpos(position.y); - view.setWidth(position.width); - view.setHeight(position.height); + + view.setWidth(size.width); + view.setHeight(size.height); view.setStartRes(av.startRes); view.setStartSeq(av.startSeq); @@ -1154,6 +1311,7 @@ public class Jalview2XML view.setFontName(av.font.getName()); view.setFontSize(av.font.getSize()); view.setFontStyle(av.font.getStyle()); + view.setScaleProteinAsCdna(av.getViewStyle().isScaleProteinAsCdna()); view.setRenderGaps(av.isRenderGaps()); view.setShowAnnotation(av.isShowAnnotation()); view.setShowBoxes(av.getShowBoxes()); @@ -1185,82 +1343,53 @@ public class Jalview2XML .getFeatureRenderer().getRenderOrder() .toArray(new String[0]); - Vector settingsAdded = new Vector(); - Object gstyle = null; - GraduatedColor gcol = null; + Vector settingsAdded = new Vector(); if (renderOrder != null) { - for (int ro = 0; ro < renderOrder.length; ro++) + for (String featureType : renderOrder) { - gstyle = ap.getSeqPanel().seqCanvas.getFeatureRenderer() - .getFeatureStyle(renderOrder[ro]); + FeatureColourI fcol = ap.getSeqPanel().seqCanvas + .getFeatureRenderer().getFeatureStyle(featureType); Setting setting = new Setting(); - setting.setType(renderOrder[ro]); - if (gstyle instanceof GraduatedColor) + setting.setType(featureType); + if (!fcol.isSimpleColour()) { - gcol = (GraduatedColor) gstyle; - setting.setColour(gcol.getMaxColor().getRGB()); - setting.setMincolour(gcol.getMinColor().getRGB()); - setting.setMin(gcol.getMin()); - setting.setMax(gcol.getMax()); - setting.setColourByLabel(gcol.isColourByLabel()); - setting.setAutoScale(gcol.isAutoScale()); - setting.setThreshold(gcol.getThresh()); - setting.setThreshstate(gcol.getThreshType()); + setting.setColour(fcol.getMaxColour().getRGB()); + setting.setMincolour(fcol.getMinColour().getRGB()); + setting.setMin(fcol.getMin()); + setting.setMax(fcol.getMax()); + setting.setColourByLabel(fcol.isColourByLabel()); + setting.setAutoScale(fcol.isAutoScaled()); + setting.setThreshold(fcol.getThreshold()); + // -1 = No threshold, 0 = Below, 1 = Above + setting.setThreshstate(fcol.isAboveThreshold() ? 1 : (fcol + .isBelowThreshold() ? 0 : -1)); } else { - setting.setColour(ap.getSeqPanel().seqCanvas - .getFeatureRenderer() - .getColour(renderOrder[ro]).getRGB()); + setting.setColour(fcol.getColour().getRGB()); } setting.setDisplay(av.getFeaturesDisplayed().isVisible( - renderOrder[ro])); + featureType)); float rorder = ap.getSeqPanel().seqCanvas.getFeatureRenderer() - .getOrder(renderOrder[ro]); + .getOrder(featureType); if (rorder > -1) { setting.setOrder(rorder); } fs.addSetting(setting); - settingsAdded.addElement(renderOrder[ro]); + settingsAdded.addElement(featureType); } } - // Make sure we save none displayed feature settings - Iterator en = ap.getSeqPanel().seqCanvas.getFeatureRenderer() - .getFeatureColours().keySet().iterator(); - while (en.hasNext()) - { - String key = en.next().toString(); - if (settingsAdded.contains(key)) - { - continue; - } - - Setting setting = new Setting(); - setting.setType(key); - setting.setColour(ap.getSeqPanel().seqCanvas.getFeatureRenderer() - .getColour(key).getRGB()); - - setting.setDisplay(false); - float rorder = ap.getSeqPanel().seqCanvas.getFeatureRenderer() - .getOrder(key); - if (rorder > -1) - { - setting.setOrder(rorder); - } - fs.addSetting(setting); - settingsAdded.addElement(key); - } // is groups actually supposed to be a map here ? - en = ap.getSeqPanel().seqCanvas.getFeatureRenderer() - .getFeatureGroups().iterator(); - Vector groupsAdded = new Vector(); + Iterator en = ap.getSeqPanel().seqCanvas + .getFeatureRenderer().getFeatureGroups().iterator(); + Vector groupsAdded = new Vector(); while (en.hasNext()) { - String grp = en.next().toString(); + String grp = en.next(); if (groupsAdded.contains(grp)) { continue; @@ -1274,7 +1403,6 @@ public class Jalview2XML groupsAdded.addElement(grp); } jms.setFeatureSettings(fs); - } if (av.hasHiddenColumns()) @@ -1372,6 +1500,10 @@ public class Jalview2XML final SequenceI jds, List viewIds, AlignmentPanel ap, boolean storeDataset) { + if (Desktop.desktop == null) + { + return; + } JInternalFrame[] frames = Desktop.desktop.getAllFrames(); for (int f = frames.length - 1; f > -1; f--) { @@ -1420,8 +1552,7 @@ public class Jalview2XML { String varnaStateFile = varna.getStateInfo(model.rna); - jarEntryName = RNA_PREFIX + viewId + "_" - + nextCounter(); + jarEntryName = RNA_PREFIX + viewId + "_" + nextCounter(); copyFileToJar(jout, varnaStateFile, jarEntryName); rnaSessions.put(model, jarEntryName); } @@ -1604,8 +1735,8 @@ public class Jalview2XML private void storeAlignmentAnnotation(AlignmentAnnotation[] aa, IdentityHashMap groupRefs, - AlignmentViewport av, - Set calcIdSet, boolean storeDS, SequenceSet vamsasSet) + AlignmentViewport av, Set calcIdSet, boolean storeDS, + SequenceSet vamsasSet) { for (int i = 0; i < aa.length; i++) @@ -1635,9 +1766,11 @@ public class Jalview2XML if (groupIdr == null) { // make a locally unique String - groupRefs.put(annotation.groupRef, + groupRefs.put( + annotation.groupRef, groupIdr = ("" + System.currentTimeMillis() - + annotation.groupRef.getName() + groupRefs.size())); + + annotation.groupRef.getName() + groupRefs + .size())); } an.setGroupRef(groupIdr.toString()); } @@ -1852,8 +1985,8 @@ public class Jalview2XML } } throw new Error(MessageManager.formatMessage( - "error.unsupported_version_calcIdparam", new Object[] - { calcIdParam.toString() })); + "error.unsupported_version_calcIdparam", + new Object[] { calcIdParam.toString() })); } /** @@ -1935,16 +2068,17 @@ public class Jalview2XML if (jds.getDatasetSequence() != null) { 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 + // seqId==dsseqid so we can tell which sequences really are // dataset sequences only - dbrefs = jds.getDBRef(); + vamsasSeq.setDsseqid(id); + dbrefs = jds.getDBRefs(); + if (parentseq == null) + { + parentseq = jds; + } } if (dbrefs != null) { @@ -1996,38 +2130,32 @@ public class Jalview2XML if (jmp.getTo() != null) { MappingChoice mpc = new MappingChoice(); - if (recurse - && (parentseq != jmp.getTo() || parentseq - .getDatasetSequence() != jmp.getTo())) + + // check/create ID for the sequence referenced by getTo() + + String jmpid = ""; + SequenceI ps = null; + if (parentseq != jmp.getTo() + && parentseq.getDatasetSequence() != jmp.getTo()) { - mpc.setSequence(createVamsasSequence(false, seqHash(jmp.getTo()), - jmp.getTo(), jds)); + // chaining dbref rather than a handshaking one + jmpid = seqHash(ps = jmp.getTo()); } else { - String jmpid = ""; - SequenceI ps = null; - if (parentseq != jmp.getTo() - && parentseq.getDatasetSequence() != jmp.getTo()) - { - // chaining dbref rather than a handshaking one - jmpid = seqHash(ps = jmp.getTo()); - } - else - { - jmpid = seqHash(ps = parentseq); - } - mpc.setDseqFor(jmpid); - if (!seqRefIds.containsKey(mpc.getDseqFor())) - { - jalview.bin.Cache.log.debug("creatign new DseqFor ID"); - seqRefIds.put(mpc.getDseqFor(), ps); - } - else - { - jalview.bin.Cache.log.debug("reusing DseqFor ID"); - } + jmpid = seqHash(ps = parentseq); + } + mpc.setDseqFor(jmpid); + if (!seqRefIds.containsKey(mpc.getDseqFor())) + { + jalview.bin.Cache.log.debug("creatign new DseqFor ID"); + seqRefIds.put(mpc.getDseqFor(), ps); + } + else + { + jalview.bin.Cache.log.debug("reusing DseqFor ID"); } + mp.setMappingChoice(mpc); } } @@ -2165,6 +2293,7 @@ public class Jalview2XML { SwingUtilities.invokeAndWait(new Runnable() { + @Override public void run() { setLoadingFinishedForNewStructureViewers(); @@ -2172,7 +2301,7 @@ public class Jalview2XML }); } catch (Exception x) { - + System.err.println("Error loading alignment: " + x.getMessage()); } } return af; @@ -2235,14 +2364,10 @@ public class Jalview2XML } if (seqRefIds == null) { - seqRefIds = new HashMap(); - } - if (frefedSequence == null) - { - frefedSequence = new Vector(); + initSeqRefs(); } - AlignFrame af = null, _af = null; + IdentityHashMap importedDatasets = new IdentityHashMap(); Map gatherToThisFrame = new HashMap(); final String file = jprovider.getFilename(); try @@ -2270,13 +2395,24 @@ public class Jalview2XML if (true) // !skipViewport(object)) { _af = loadFromObject(object, file, true, jprovider); - if (object.getJalviewModelSequence().getViewportCount() > 0) + if (_af != null + && object.getJalviewModelSequence().getViewportCount() > 0) { - af = _af; - if (af.viewport.isGatherViewsHere()) + if (af == null) { - gatherToThisFrame.put(af.viewport.getSequenceSetId(), af); + // store a reference to the first view + af = _af; } + if (_af.viewport.isGatherViewsHere()) + { + // if this is a gathered view, keep its reference since + // after gathering views, only this frame will remain + af = _af; + gatherToThisFrame.put(_af.viewport.getSequenceSetId(), _af); + } + // Save dataset to register mappings once all resolved + importedDatasets.put(af.viewport.getAlignment().getDataset(), + af.viewport.getAlignment().getDataset()); } } entryCount++; @@ -2332,11 +2468,6 @@ public class Jalview2XML 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 @@ -2350,11 +2481,24 @@ public class Jalview2XML } restoreSplitFrames(); - + for (AlignmentI ds : importedDatasets.keySet()) + { + if (ds.getCodonFrames() != null) + { + StructureSelectionManager.getStructureSelectionManager( + Desktop.instance).registerMappings(ds.getCodonFrames()); + } + } if (errorMessage != null) { reportErrors(); } + + if (Desktop.instance != null) + { + Desktop.instance.stopLoading(); + } + return af; } @@ -2399,6 +2543,8 @@ public class Jalview2XML SplitFrame sf = createSplitFrame(dnaFrame, af); addedToSplitFrames.add(dnaFrame); addedToSplitFrames.add(af); + dnaFrame.setMenusForViewport(); + af.setMenusForViewport(); if (af.viewport.isGatherViewsHere()) { gatherTo.add(sf); @@ -2415,10 +2561,12 @@ public class Jalview2XML .entrySet()) { AlignFrame af = candidate.getValue(); - if (!addedToSplitFrames.contains(af)) { + if (!addedToSplitFrames.contains(af)) + { Viewport view = candidate.getKey(); Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(), view.getHeight()); + af.setMenusForViewport(); System.err.println("Failed to restore view " + view.getTitle() + " to split frame"); } @@ -2450,6 +2598,11 @@ public class Jalview2XML 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); /* @@ -2517,14 +2670,16 @@ public class Jalview2XML * @param pdbId * @return */ - String loadPDBFile(jarInputStreamProvider jprovider, String pdbId) + String loadPDBFile(jarInputStreamProvider jprovider, String pdbId, + String origFile) { if (alreadyLoadedPDB.containsKey(pdbId)) { return alreadyLoadedPDB.get(pdbId).toString(); } - String tempFile = copyJarEntry(jprovider, pdbId, "jalview_pdb"); + String tempFile = copyJarEntry(jprovider, pdbId, "jalview_pdb", + origFile); if (tempFile != null) { alreadyLoadedPDB.put(pdbId, tempFile); @@ -2541,14 +2696,26 @@ public class Jalview2XML * @param prefix * a prefix for the temporary file name, must be at least three * characters long + * @param origFile + * null or original file - so new file can be given the same suffix + * as the old one * @return */ protected String copyJarEntry(jarInputStreamProvider jprovider, - String jarEntryName, String prefix) + String jarEntryName, String prefix, String origFile) { BufferedReader in = null; PrintWriter out = null; - + String suffix = ".tmp"; + if (origFile == null) + { + origFile = jarEntryName; + } + int sfpos = origFile.lastIndexOf("."); + if (sfpos > -1 && sfpos < (origFile.length() - 3)) + { + suffix = "." + origFile.substring(sfpos + 1); + } try { JarInputStream jin = jprovider.getJarInputStream(); @@ -2566,7 +2733,7 @@ public class Jalview2XML if (entry != null) { in = new BufferedReader(new InputStreamReader(jin, UTF_8)); - File outFile = File.createTempFile(prefix, ".tmp"); + File outFile = File.createTempFile(prefix, suffix); outFile.deleteOnExit(); out = new PrintWriter(new FileOutputStream(outFile)); String data; @@ -2654,36 +2821,71 @@ public class Jalview2XML // LOAD SEQUENCES List hiddenSeqs = null; - jalview.datamodel.Sequence jseq; List tmpseqs = new ArrayList(); 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(); - if (seqRefIds.get(seqId) != null) + SequenceI tmpSeq = seqRefIds.get(seqId); + if (tmpSeq != null) { - tmpseqs.add(seqRefIds.get(seqId)); - multipleView = true; + if (!incompleteSeqs.containsKey(seqId)) + { + // may not need this check, but keep it for at least 2.9,1 release + if (tmpSeq.getStart() != jseqs[i].getStart() + || tmpSeq.getEnd() != jseqs[i].getEnd()) + { + System.err + .println("Warning JAL-2154 regression: updating start/end for sequence " + + tmpSeq.toString() + " to " + jseqs[i]); + } + } + else + { + incompleteSeqs.remove(seqId); + } + if (vamsasSeq.length > vi && vamsasSeq[vi].getId().equals(seqId)) + { + // most likely we are reading a dataset XML document so + // update from vamsasSeq section of XML for this sequence + tmpSeq.setName(vamsasSeq[vi].getName()); + tmpSeq.setDescription(vamsasSeq[vi].getDescription()); + tmpSeq.setSequence(vamsasSeq[vi].getSequence()); + vi++; + } + else + { + // reading multiple views, so vamsasSeq set is a subset of JSeq + multipleView = true; + } + tmpSeq.setStart(jseqs[i].getStart()); + tmpSeq.setEnd(jseqs[i].getEnd()); + tmpseqs.add(tmpSeq); } else { - jseq = new jalview.datamodel.Sequence(vamsasSeq[vi].getName(), + tmpSeq = new jalview.datamodel.Sequence(vamsasSeq[vi].getName(), vamsasSeq[vi].getSequence()); - jseq.setDescription(vamsasSeq[vi].getDescription()); - jseq.setStart(jseqs[i].getStart()); - jseq.setEnd(jseqs[i].getEnd()); - jseq.setVamsasId(uniqueSetSuffix + seqId); - seqRefIds.put(vamsasSeq[vi].getId(), jseq); - tmpseqs.add(jseq); + 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) @@ -2691,9 +2893,8 @@ public class Jalview2XML hiddenSeqs = new ArrayList(); } - hiddenSeqs.add(seqRefIds.get(seqId)); + hiddenSeqs.add(tmpSeq); } - } // / @@ -2702,31 +2903,51 @@ public class Jalview2XML SequenceI[] orderedSeqs = tmpseqs .toArray(new SequenceI[tmpseqs.size()]); - Alignment al = new Alignment(orderedSeqs); - - // / 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 + AlignmentI al = null; + // so we must create or recover the dataset alignment before going further // /////////////////////////////// if (vamsasSet.getDatasetId() == null || vamsasSet.getDatasetId() == "") { - // older jalview projects do not have a dataset id. + // older jalview projects do not have a dataset - so creat alignment and + // dataset + al = new Alignment(orderedSeqs); 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); + boolean isdsal = object.getJalviewModelSequence().getViewportCount() == 0; + if (isdsal) + { + // we are importing a dataset record, so + // recover reference to an alignment already materialsed as dataset + al = getDatasetFor(vamsasSet.getDatasetId()); + } + if (al == null) + { + // materialse the alignment + al = new Alignment(orderedSeqs); + } + if (isdsal) + { + addDatasetRef(vamsasSet.getDatasetId(), al); + } + + // finally, verify all data in vamsasSet is actually present in al + // passing on flag indicating if it is actually a stored dataset + recoverDatasetFor(vamsasSet, al, isdsal); + } + + 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()); } + // /////////////////////////////// Hashtable pdbloaded = new Hashtable(); // TODO nothing writes to this?? @@ -2734,6 +2955,12 @@ public class Jalview2XML { // load sequence features, database references and any associated PDB // structures for the alignment + // + // prior to 2.10, this part would only be executed the first time a + // sequence was encountered, but not afterwards. + // now, for 2.10 projects, this is also done if the xml doc includes + // dataset sequences not actually present in any particular view. + // for (int i = 0; i < vamsasSeq.length; i++) { if (jseqs[i].getFeaturesCount() > 0) @@ -2760,13 +2987,17 @@ public class Jalview2XML } } - - al.getSequenceAt(i).getDatasetSequence().addSequenceFeature(sf); + // adds feature to datasequence's feature set (since Jalview 2.10) + al.getSequenceAt(i).addSequenceFeature(sf); } } if (vamsasSeq[i].getDBRefCount() > 0) { - addDBRefs(al.getSequenceAt(i).getDatasetSequence(), vamsasSeq[i]); + // adds dbrefs to datasequence's set (since Jalview 2.10) + addDBRefs( + al.getSequenceAt(i).getDatasetSequence() == null ? al.getSequenceAt(i) + : al.getSequenceAt(i).getDatasetSequence(), + vamsasSeq[i]); } if (jseqs[i].getPdbidsCount() > 0) { @@ -2777,29 +3008,49 @@ public class Jalview2XML entry.setId(ids[p].getId()); if (ids[p].getType() != null) { - if (ids[p].getType().equalsIgnoreCase("PDB")) + if (PDBEntry.Type.getType(ids[p].getType()) != null) { - entry.setType(PDBEntry.Type.PDB); + entry.setType(PDBEntry.Type.getType(ids[p].getType())); } else { entry.setType(PDBEntry.Type.FILE); } } - if (ids[p].getFile() != null) + // jprovider is null when executing 'New View' + if (ids[p].getFile() != null && jprovider != null) { if (!pdbloaded.containsKey(ids[p].getFile())) { - entry.setFile(loadPDBFile(jprovider, ids[p].getId())); + entry.setFile(loadPDBFile(jprovider, ids[p].getId(), + ids[p].getFile())); } else { entry.setFile(pdbloaded.get(ids[p].getId()).toString()); } } + if (ids[p].getPdbentryItem() != null) + { + for (PdbentryItem item : ids[p].getPdbentryItem()) + { + for (Property pr : item.getProperty()) + { + entry.setProperty(pr.getName(), pr.getValue()); + } + } + } StructureSelectionManager.getStructureSelectionManager( Desktop.instance).registerPDBEntry(entry); - al.getSequenceAt(i).getDatasetSequence().addPDBId(entry); + // adds PDBEntry to datasequence's set (since Jalview 2.10) + if (al.getSequenceAt(i).getDatasetSequence() != null) + { + al.getSequenceAt(i).getDatasetSequence().addPDBId(entry); + } + else + { + al.getSequenceAt(i).addPDBId(entry); + } } } } @@ -2828,20 +3079,20 @@ public class Jalview2XML if (maps[m].getMapping() != null) { mapping = addMapping(maps[m].getMapping()); - } - if (dnaseq != null) - { - cf.addMap(dnaseq, mapping.getTo(), mapping.getMap()); - } - else - { - // defer to later - frefedSequence.add(new Object[] - { maps[m].getDnasq(), cf, mapping }); + if (dnaseq != null && mapping.getTo() != null) + { + cf.addMap(dnaseq, mapping.getTo(), mapping.getMap()); + } + else + { + // defer to later + frefedSequence.add(newAlcodMapRef(maps[m].getDnasq(), cf, + mapping)); + } } } + al.addCodonFrame(cf); } - al.addCodonFrame(cf); } } @@ -2888,8 +3139,7 @@ public class Jalview2XML // set visiblity for other annotation in this view String annotationId = annotation.getId(); - if (annotationId != null - && annotationIds.containsKey(annotationId)) + if (annotationId != null && annotationIds.containsKey(annotationId)) { AlignmentAnnotation jda = annotationIds.get(annotationId); // in principle Visible should always be true for annotation displayed @@ -3123,8 +3373,7 @@ public class Jalview2XML SequenceGroup sg = new SequenceGroup(seqs, jGroup.getName(), cs, jGroup.getDisplayBoxes(), jGroup.getDisplayText(), - jGroup.getColourText(), jGroup.getStart(), - jGroup.getEnd()); + jGroup.getColourText(), jGroup.getStart(), jGroup.getEnd()); sg.setOutlineColour(new java.awt.Color(jGroup.getOutlineColour())); @@ -3152,8 +3401,7 @@ public class Jalview2XML } if (jGroup.getConsThreshold() != 0) { - jalview.analysis.Conservation c = new jalview.analysis.Conservation( - "All", ResidueProperties.propHash, 3, + Conservation c = new Conservation("All", 3, sg.getSequences(null), 0, sg.getWidth() - 1); c.calculate(); c.verdict(false, 25); @@ -3163,8 +3411,8 @@ public class Jalview2XML if (jGroup.getId() != null && groupAnnotRefs.size() > 0) { // re-instate unique group/annotation row reference - List jaal = groupAnnotRefs - .get(jGroup.getId()); + List jaal = groupAnnotRefs.get(jGroup + .getId()); if (jaal != null) { for (AlignmentAnnotation jaa : jaal) @@ -3192,8 +3440,8 @@ public class Jalview2XML if (addAnnotSchemeGroup) { // reconstruct the annotation colourscheme - sg.cs = constructAnnotationColour( - jGroup.getAnnotationColours(), null, al, jms, false); + sg.cs = constructAnnotationColour(jGroup.getAnnotationColours(), + null, al, jms, false); } } } @@ -3249,8 +3497,8 @@ public class Jalview2XML * indicate that annotation colours are applied across all groups (pre * Jalview 2.8.1 behaviour) */ - boolean doGroupAnnColour = isVersionStringLaterThan("2.8.1", - object.getVersion()); + boolean doGroupAnnColour = Jalview2XML.isVersionStringLaterThan( + "2.8.1", object.getVersion()); AlignmentPanel ap = null; boolean isnewview = true; @@ -3325,8 +3573,8 @@ public class Jalview2XML for (int i = 0; i < jseq.getRnaViewerCount(); i++) { RnaViewer viewer = jseq.getRnaViewer(i); - AppVarna appVarna = findOrCreateVarnaViewer(viewer, uniqueSetSuffix, - ap); + AppVarna appVarna = findOrCreateVarnaViewer(viewer, + uniqueSetSuffix, ap); for (int j = 0; j < viewer.getSecondaryStructureCount(); j++) { @@ -3343,12 +3591,11 @@ public class Jalview2XML String rnaTitle = ss.getTitle(); String sessionState = ss.getViewerState(); String tempStateFile = copyJarEntry(jprovider, sessionState, - "varna"); - RnaModel rna = new RnaModel(rnaTitle, ann, seq, null, gapped, - tempStateFile); - appVarna.addModel(rna, rnaTitle); + "varna", null); + RnaModel rna = new RnaModel(rnaTitle, ann, seq, null, gapped); + appVarna.addModelSession(rna, rnaTitle, tempStateFile); } - appVarna.setSelectedIndex(viewer.getSelectedRna()); + appVarna.setInitialSelection(viewer.getSelectedRna()); } } } @@ -3389,8 +3636,8 @@ public class Jalview2XML * viewer not found - make it */ RnaViewerModel model = new RnaViewerModel(postLoadId, - viewer.getTitle(), viewer.getXpos(), - viewer.getYpos(), viewer.getWidth(), viewer.getHeight(), + viewer.getTitle(), viewer.getXpos(), viewer.getYpos(), + viewer.getWidth(), viewer.getHeight(), viewer.getDividerLocation()); AppVarna varna = new AppVarna(model, ap); @@ -3519,7 +3766,8 @@ public class Jalview2XML // Originally : ids[p].getFile() // : TODO: verify external PDB file recovery still works in normal // jalview project load - jpdb.setFile(loadPDBFile(jprovider, ids[p].getId())); + jpdb.setFile(loadPDBFile(jprovider, ids[p].getId(), + ids[p].getFile())); jpdb.setId(ids[p].getId()); int x = structureState.getXpos(); @@ -3530,7 +3778,8 @@ public class Jalview2XML // Probably don't need to do this anymore... // Desktop.desktop.getComponentAt(x, y); // TODO: NOW: check that this recovers the PDB file correctly. - String pdbFile = loadPDBFile(jprovider, ids[p].getId()); + String pdbFile = loadPDBFile(jprovider, ids[p].getId(), + ids[p].getFile()); jalview.datamodel.SequenceI seq = seqRefIds.get(jseqs[i] .getId() + ""); if (sviewid == null) @@ -3675,12 +3924,12 @@ public class Jalview2XML * @param af * @param jprovider */ - protected void createChimeraViewer(Entry viewerData, - AlignFrame af, + protected void createChimeraViewer( + Entry viewerData, AlignFrame af, jarInputStreamProvider jprovider) { StructureViewerModel data = viewerData.getValue(); - String chimeraSessionFile = data.getStateData(); + String chimeraSessionFile = data.getStateData(); /* * Copy Chimera session from jar entry "viewer_"+viewId to a temporary file @@ -3690,7 +3939,7 @@ public class Jalview2XML */ String viewerJarEntryName = getViewerJarEntryName(data.getViewId()); chimeraSessionFile = copyJarEntry(jprovider, viewerJarEntryName, - "chimera"); + "chimera", null); Set> fileData = data.getFileData() .entrySet(); @@ -3717,8 +3966,8 @@ public class Jalview2XML String newViewId = viewerData.getKey(); ChimeraViewFrame cvf = new ChimeraViewFrame(chimeraSessionFile, - af.alignPanel, pdbArray, - seqsArray, colourByChimera, colourBySequence, newViewId); + af.alignPanel, pdbArray, seqsArray, colourByChimera, + colourBySequence, newViewId); cvf.setSize(data.getWidth(), data.getHeight()); cvf.setLocation(data.getX(), data.getY()); } @@ -3771,6 +4020,11 @@ public class Jalview2XML // filename // translation differently. StructureData filedat = oldFiles.get(new File(oldfilenam)); + if (filedat == null) + { + String reformatedOldFilename = oldfilenam.replaceAll("/", "\\\\"); + filedat = oldFiles.get(new File(reformatedOldFilename)); + } newFileLoc.append(Platform.escapeString(filedat.getFilePath())); pdbfilenames.add(filedat.getFilePath()); pdbids.add(filedat.getPdbId()); @@ -3807,16 +4061,23 @@ public class Jalview2XML newFileLoc.append(";"); } - if (newFileLoc.length() > 0) + if (newFileLoc.length() == 0) { - int histbug = newFileLoc.indexOf("history = "); + return; + } + int histbug = newFileLoc.indexOf("history = "); + if (histbug > -1) + { + /* + * change "history = [true|false];" to "history = [1|0];" + */ 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.contains("e")) // eh? what can it be? { if (val.trim().equals("true")) { @@ -3829,54 +4090,55 @@ public class Jalview2XML newFileLoc.replace(histbug, diff, val); } } + } - final String[] pdbf = pdbfilenames.toArray(new String[pdbfilenames - .size()]); - final String[] id = pdbids.toArray(new String[pdbids.size()]); - final SequenceI[][] sq = seqmaps - .toArray(new SequenceI[seqmaps.size()][]); - final String fileloc = newFileLoc.toString(); - final String sviewid = viewerData.getKey(); - final AlignFrame alf = af; - final Rectangle rect = new Rectangle(svattrib.getX(), - svattrib.getY(), svattrib.getWidth(), svattrib.getHeight()); - try + final String[] pdbf = pdbfilenames.toArray(new String[pdbfilenames + .size()]); + final String[] id = pdbids.toArray(new String[pdbids.size()]); + final SequenceI[][] sq = seqmaps + .toArray(new SequenceI[seqmaps.size()][]); + final String fileloc = newFileLoc.toString(); + final String sviewid = viewerData.getKey(); + final AlignFrame alf = af; + final Rectangle rect = new Rectangle(svattrib.getX(), svattrib.getY(), + svattrib.getWidth(), svattrib.getHeight()); + try + { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { - javax.swing.SwingUtilities.invokeAndWait(new Runnable() + @Override + public void run() { - @Override - public void run() + JalviewStructureDisplayI sview = null; + try { - JalviewStructureDisplayI sview = null; - try - { - sview = new StructureViewer(alf.alignPanel - .getStructureSelectionManager()).createView( - StructureViewer.ViewerType.JMOL, pdbf, id, sq, - alf.alignPanel, svattrib, fileloc, rect, sviewid); - addNewStructureViewer(sview); - } catch (OutOfMemoryError ex) + sview = new StructureViewer(alf.alignPanel + .getStructureSelectionManager()).createView( + StructureViewer.ViewerType.JMOL, pdbf, id, sq, + alf.alignPanel, svattrib, fileloc, rect, sviewid); + addNewStructureViewer(sview); + } catch (OutOfMemoryError ex) + { + new OOMWarning("restoring structure view for PDB id " + id, + (OutOfMemoryError) ex.getCause()); + if (sview != null && sview.isVisible()) { - new OOMWarning("restoring structure view for PDB id " + id, - (OutOfMemoryError) ex.getCause()); - if (sview != null && sview.isVisible()) - { - sview.closeViewer(false); - sview.setVisible(false); - sview.dispose(); - } + sview.closeViewer(false); + sview.setVisible(false); + sview.dispose(); } } - }); - } catch (InvocationTargetException ex) - { - warn("Unexpected error when opening Jmol view.", ex); + } + }); + } catch (InvocationTargetException ex) + { + warn("Unexpected error when opening Jmol view.", ex); - } catch (InterruptedException e) - { - // e.printStackTrace(); - } + } catch (InterruptedException e) + { + // e.printStackTrace(); } + } /** @@ -4021,18 +4283,22 @@ public class Jalview2XML } /** + * Answers true if 'version' is equal to or later than 'supported', where each + * is formatted as major/minor versions like "2.8.3" or "2.3.4b1" for bugfix + * changes. Development and test values for 'version' are leniently treated + * i.e. answer true. * * @param supported * - minimum version we are comparing against * @param version - * - version of data being processsed. - * @return true if version is development/null or evaluates to the same or - * later X.Y.Z (where X,Y,Z are like [0-9]+b?[0-9]*) + * - version of data being processsed + * @return */ - protected boolean isVersionStringLaterThan(String supported, + public static boolean isVersionStringLaterThan(String supported, String version) { - if (version == null || version.equalsIgnoreCase("DEVELOPMENT BUILD") + if (supported == null || version == null + || version.equalsIgnoreCase("DEVELOPMENT BUILD") || version.equalsIgnoreCase("Test") || version.equalsIgnoreCase("AUTOMATED BUILD")) { @@ -4043,38 +4309,8 @@ public class Jalview2XML } else { - StringTokenizer currentV = new StringTokenizer(supported, "."), fileV = new StringTokenizer( - version, "."); - while (currentV.hasMoreTokens() && fileV.hasMoreTokens()) - { - // convert b to decimal to catch bugfix releases within a series - String curT = currentV.nextToken().toLowerCase().replace('b', '.'); - String fileT = fileV.nextToken().toLowerCase().replace('b', '.'); - try - { - if (Float.valueOf(curT) > Float.valueOf(fileT)) - { - // current version is newer than the version that wrote the file - return false; - } - } catch (NumberFormatException nfe) - { - System.err - .println("** WARNING: Version comparison failed for tokens (" - + curT - + ") and (" - + fileT - + ")\n** Current: '" - + supported + "' and Version: '" + version + "'"); - } - } - if (currentV.hasMoreElements()) - { - // fileV has no minor version but identical series to current - return false; - } + return StringUtils.compareVersions(version, supported, "b") >= 0; } - return true; } Vector newStructureViewers = null; @@ -4102,7 +4338,7 @@ public class Jalview2XML } AlignFrame loadViewport(String file, JSeq[] JSEQ, - List hiddenSeqs, Alignment al, + List hiddenSeqs, AlignmentI al, JalviewModelSequence jms, Viewport view, String uniqueSeqSetId, String viewId, List autoAlan) { @@ -4118,6 +4354,12 @@ public class Jalview2XML .getSequenceAt(i), new java.awt.Color(JSEQ[i].getColour())); } + if (al.hasSeqrep()) + { + af.getViewport().setColourByReferenceSeq(true); + af.getViewport().setDisplayReferenceSeq(true); + } + af.viewport.setGatherViewsHere(view.getGatheredViews()); if (view.getSequenceSetId() != null) @@ -4144,25 +4386,25 @@ public class Jalview2XML { for (int s = 0; s < JSEQ.length; s++) { - jalview.datamodel.SequenceGroup hidden = new jalview.datamodel.SequenceGroup(); - + SequenceGroup hidden = new SequenceGroup(); + boolean isRepresentative = false; for (int r = 0; r < JSEQ[s].getHiddenSequencesCount(); r++) { - hidden.addSequence( - al.getSequenceAt(JSEQ[s].getHiddenSequences(r)), false); + isRepresentative = true; + SequenceI sequenceToHide = al.getSequenceAt(JSEQ[s] + .getHiddenSequences(r)); + hidden.addSequence(sequenceToHide, false); + // remove from hiddenSeqs list so we don't try to hide it twice + hiddenSeqs.remove(sequenceToHide); + } + if (isRepresentative) + { + SequenceI representativeSequence = al.getSequenceAt(s); + hidden.addSequence(representativeSequence, false); + af.viewport.hideRepSequences(representativeSequence, hidden); } - 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); - // } - SequenceI[] hseqs = hiddenSeqs.toArray(new SequenceI[hiddenSeqs .size()]); af.viewport.hideSequence(hseqs); @@ -4188,6 +4430,9 @@ public class Jalview2XML af.viewport.setFont( new java.awt.Font(view.getFontName(), view.getFontStyle(), view .getFontSize()), true); + ViewStyleI vs = af.viewport.getViewStyle(); + vs.setScaleProteinAsCdna(view.isScaleProteinAsCdna()); + af.viewport.setViewStyle(vs); // TODO: allow custom charWidth/Heights to be restored by updating them // after setting font - which means set above to false af.viewport.setRenderGaps(view.getRenderGaps()); @@ -4318,25 +4563,33 @@ public class Jalview2XML af.viewport.setFeaturesDisplayed(fdi = new FeaturesDisplayed()); String[] renderOrder = new String[jms.getFeatureSettings() .getSettingCount()]; - Hashtable featureGroups = new Hashtable(); - Hashtable featureColours = new Hashtable(); - Hashtable featureOrder = new Hashtable(); + Map featureColours = new Hashtable(); + Map featureOrder = new Hashtable(); 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); + FeatureColourI gc = setting.hasMin() ? new FeatureColour( + new Color(setting.getMincolour()), new Color( + setting.getColour()), setting.getMin(), + setting.getMax()) : new FeatureColour(new Color( + setting.getMincolour()), new Color(setting.getColour()), + 0, 1); if (setting.hasThreshold()) { - gc.setThresh(setting.getThreshold()); - gc.setThreshType(setting.getThreshstate()); + gc.setThreshold(setting.getThreshold()); + int threshstate = setting.getThreshstate(); + // -1 = None, 0 = Below, 1 = Above threshold + if (threshstate == 0) + { + gc.setBelowThreshold(true); + } + else if (threshstate == 1) + { + gc.setAboveThreshold(true); + } } gc.setAutoScaled(true); // default if (setting.hasAutoScale()) @@ -4352,8 +4605,8 @@ public class Jalview2XML } else { - featureColours.put(setting.getType(), - new java.awt.Color(setting.getColour())); + featureColours.put(setting.getType(), new FeatureColour( + new Color(setting.getColour()))); } renderOrder[fs] = setting.getType(); if (setting.hasOrder()) @@ -4370,7 +4623,7 @@ public class Jalview2XML fdi.setVisible(setting.getType()); } } - Hashtable fgtable = new Hashtable(); + Map fgtable = new Hashtable(); for (int gs = 0; gs < jms.getFeatureSettings().getGroupCount(); gs++) { Group grp = jms.getFeatureSettings().getGroup(gs); @@ -4413,7 +4666,7 @@ public class Jalview2XML } } af.setMenusFromViewport(af.viewport); - + af.setTitle(view.getTitle()); // TODO: we don't need to do this if the viewport is aready visible. /* * Add the AlignFrame to the desktop (it may be 'gathered' later), unless it @@ -4438,7 +4691,7 @@ public class Jalview2XML } private ColourSchemeI constructAnnotationColour( - AnnotationColours viewAnnColour, AlignFrame af, Alignment al, + AnnotationColours viewAnnColour, AlignFrame af, AlignmentI al, JalviewModelSequence jms, boolean checkGroupAnnColour) { boolean propagateAnnColour = false; @@ -4562,7 +4815,7 @@ public class Jalview2XML return cs; } - private void reorderAutoannotation(AlignFrame af, Alignment al, + private void reorderAutoannotation(AlignFrame af, AlignmentI al, List autoAlan) { // copy over visualization settings for autocalculated annotation in the @@ -4572,8 +4825,8 @@ public class Jalview2XML /** * Kludge for magic autoannotation names (see JAL-811) */ - String[] magicNames = new String[] - { "Consensus", "Quality", "Conservation" }; + String[] magicNames = new String[] { "Consensus", "Quality", + "Conservation" }; JvAnnotRow nullAnnot = new JvAnnotRow(-1, null); Hashtable visan = new Hashtable(); for (String nm : magicNames) @@ -4717,10 +4970,11 @@ public class Jalview2XML } } - private void recoverDatasetFor(SequenceSet vamsasSet, Alignment al, + private void recoverDatasetFor(SequenceSet vamsasSet, AlignmentI al, boolean ignoreUnrefed) { - jalview.datamodel.Alignment ds = getDatasetFor(vamsasSet.getDatasetId()); + jalview.datamodel.AlignmentI ds = getDatasetFor(vamsasSet + .getDatasetId()); Vector dseqs = null; if (ds == null) { @@ -4730,7 +4984,7 @@ public class Jalview2XML for (int i = 0, iSize = vamsasSet.getSequenceCount(); i < iSize; i++) { Sequence vamsasSeq = vamsasSet.getSequence(i); - ensureJalviewDatasetSequence(vamsasSeq, ds, dseqs, ignoreUnrefed); + ensureJalviewDatasetSequence(vamsasSeq, ds, dseqs, ignoreUnrefed, i); } // create a new dataset if (ds == null) @@ -4757,18 +5011,29 @@ public class Jalview2XML * dataset alignment * @param dseqs * vector to add new dataset sequence to + * @param ignoreUnrefed + * - when true, don't create new sequences from vamsasSeq if it's id + * doesn't already have an asssociated Jalview sequence. + * @param vseqpos + * - used to reorder the sequence in the alignment according to the + * vamsasSeq array ordering, to preserve ordering of dataset */ private void ensureJalviewDatasetSequence(Sequence vamsasSeq, - AlignmentI ds, Vector dseqs, boolean ignoreUnrefed) + AlignmentI ds, Vector dseqs, boolean ignoreUnrefed, int vseqpos) { // JBP TODO: Check this is called for AlCodonFrames to support recovery of // xRef Codon Maps SequenceI sq = seqRefIds.get(vamsasSeq.getId()); + boolean reorder = false; SequenceI dsq = null; if (sq != null && sq.getDatasetSequence() != null) { dsq = sq.getDatasetSequence(); } + else + { + reorder = true; + } if (sq == null && ignoreUnrefed) { return; @@ -4864,21 +5129,50 @@ public class Jalview2XML // + (post ? "appended" : "")); } } + else + { + // sequence refs are identical. We may need to update the existing dataset + // alignment with this one, though. + if (ds != null && dseqs == null) + { + int opos = ds.findIndex(dsq); + SequenceI tseq = null; + if (opos != -1 && vseqpos != opos) + { + // remove from old position + ds.deleteSequence(dsq); + } + if (vseqpos < ds.getHeight()) + { + if (vseqpos != opos) + { + // save sequence at destination position + tseq = ds.getSequenceAt(vseqpos); + ds.replaceSequenceAt(vseqpos, dsq); + ds.addSequence(tseq); + } + } + else + { + ds.addSequence(dsq); + } + } + } } /* * TODO use AlignmentI here and in related methods - needs * AlignmentI.getDataset() changed to return AlignmentI instead of Alignment */ - Hashtable datasetIds = null; + Hashtable datasetIds = null; - IdentityHashMap dataset2Ids = null; + IdentityHashMap dataset2Ids = null; - private Alignment getDatasetFor(String datasetId) + private AlignmentI getDatasetFor(String datasetId) { if (datasetIds == null) { - datasetIds = new Hashtable(); + datasetIds = new Hashtable(); return null; } if (datasetIds.containsKey(datasetId)) @@ -4888,11 +5182,11 @@ public class Jalview2XML return null; } - private void addDatasetRef(String datasetId, Alignment dataset) + private void addDatasetRef(String datasetId, AlignmentI dataset) { if (datasetIds == null) { - datasetIds = new Hashtable(); + datasetIds = new Hashtable(); } datasetIds.put(datasetId, dataset); } @@ -4903,7 +5197,7 @@ public class Jalview2XML * @param dataset * @return */ - private String getDatasetIdRef(Alignment dataset) + private String getDatasetIdRef(AlignmentI dataset) { if (dataset.getDataset() != null) { @@ -4915,7 +5209,7 @@ public class Jalview2XML // make a new datasetId and record it if (dataset2Ids == null) { - dataset2Ids = new IdentityHashMap(); + dataset2Ids = new IdentityHashMap(); } else { @@ -4983,8 +5277,7 @@ public class Jalview2XML } else { - frefedSequence.add(new Object[] - { dsfor, jmap }); + frefedSequence.add(newMappingRef(dsfor, jmap)); } } else @@ -5022,6 +5315,7 @@ public class Jalview2XML djs.setEnd(jmap.getMap().getToHighest()); djs.setVamsasId(uniqueSetSuffix + sqid); jmap.setTo(djs); + incompleteSeqs.put(sqid, djs); seqRefIds.put(sqid, djs); } @@ -5318,7 +5612,7 @@ public class Jalview2XML } } } - + return result; }