Merge branch 'features/JAL-1956_featureStyles' into merge_JAL-1956
authorJim Procter <jprocter@issues.jalview.org>
Tue, 21 Jun 2016 13:53:15 +0000 (14:53 +0100)
committerJim Procter <jprocter@issues.jalview.org>
Tue, 21 Jun 2016 13:53:15 +0000 (14:53 +0100)
1  2 
src/jalview/gui/Jalview2XML.java
test/jalview/io/FeaturesFileTest.java

@@@ -20,6 -20,7 +20,7 @@@
   */
  package jalview.gui;
  
+ import jalview.api.FeatureColourI;
  import jalview.api.ViewStyleI;
  import jalview.api.structures.JalviewStructureDisplayI;
  import jalview.bin.Cache;
@@@ -71,7 -72,7 +72,7 @@@ import jalview.schemabinding.version2.V
  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;
@@@ -79,7 -80,6 +80,7 @@@ import jalview.structure.StructureSelec
  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;
@@@ -118,6 -118,7 +119,6 @@@ 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;
@@@ -634,15 -635,11 +635,15 @@@ public class Jalview2XM
      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();
        {
          // switch jal and the dataset
          jal = jal.getDataset();
 +        rjal = jal;
        }
      }
      if (jal.getProperties() != null)
      Set<String> calcIdSet = new HashSet<String>();
  
      // SAVE SEQUENCES
 -    for (int i = 0; i < jal.getHeight(); i++)
 +    for (int i = 0; i < rjal.getHeight(); i++)
      {
 -      final SequenceI jds = jal.getSequenceAt(i);
 +      final SequenceI jds = rjal.getSequenceAt(i);
        final SequenceI jdatasq = jds.getDatasetSequence() == null ? jds
                : jds.getDatasetSequence();
        String id = seqHash(jds);
          // 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(rjal.getSequenceAt(i)))
            {
              jalview.datamodel.SequenceI[] reps = av
 -                    .getRepresentedSequences(jal.getSequenceAt(i))
 -                    .getSequencesInOrder(jal);
 +                    .getRepresentedSequences(rjal.getSequenceAt(i))
 +                    .getSequencesInOrder(rjal);
  
              for (int h = 0; h < reps.length; h++)
              {
 -              if (reps[h] != jal.getSequenceAt(i))
 +              if (reps[h] != rjal.getSequenceAt(i))
                {
 -                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(rjal.getSequenceAt(i) == 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();
              alc.addAlcodMap(alcmap);
            }
          }
 -
 +        // TODO: delete this ? dead code from 2.8.3->2.9 ?
          // {
          // AlcodonFrame alc = new AlcodonFrame();
          // vamsasSet.addAlcodonFrame(alc);
                  .toArray(new String[0]);
  
          Vector<String> settingsAdded = new Vector<String>();
-         Object gstyle = null;
-         GraduatedColor gcol = null;
          if (renderOrder != null)
          {
            for (String featureType : renderOrder)
            {
-             gstyle = ap.getSeqPanel().seqCanvas.getFeatureRenderer()
+             FeatureColourI fcol = ap.getSeqPanel().seqCanvas
+                     .getFeatureRenderer()
                      .getFeatureStyle(featureType);
              Setting setting = new Setting();
              setting.setType(featureType);
-             if (gstyle instanceof GraduatedColor)
+             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(((Color) gstyle).getRGB());
+               setting.setColour(fcol.getColour().getRGB());
              }
  
              setting.setDisplay(av.getFeaturesDisplayed().isVisible(
            groupsAdded.addElement(grp);
          }
          jms.setFeatureSettings(fs);
        }
  
        if (av.hasHiddenColumns())
      List<SequenceI> tmpseqs = new ArrayList<SequenceI>();
  
      boolean multipleView = false;
 -
 +    SequenceI referenceseqForView = null;
      JSeq[] jseqs = object.getJalviewModelSequence().getJSeq();
      int vi = 0; // counter in vamsasSeq array
      for (int i = 0; i < jseqs.length; i++)
          vi++;
        }
  
 +      if (jseqs[i].hasViewreference() && jseqs[i].getViewreference())
 +      {
 +        referenceseqForView = tmpseqs.get(tmpseqs.size() - 1);
 +      }
 +
        if (jseqs[i].getHidden())
        {
          if (hiddenSeqs == null)
  
          hiddenSeqs.add(seqRefIds.get(seqId));
        }
 -
      }
  
      // /
  
      Alignment al = new Alignment(orderedSeqs);
  
 +    if (referenceseqForView != null)
 +    {
 +      al.setSeqrep(referenceseqForView);
 +    }
      // / Add the alignment properties
      for (int i = 0; i < vamsasSet.getSequenceSetPropertiesCount(); i++)
      {
    }
  
    /**
 +   * 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
     */
    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"))
      {
      }
      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
 -        {
 -          float supportedVersionToken = Float.parseFloat(curT);
 -          float myVersiontoken = Float.parseFloat(fileT);
 -          if (supportedVersionToken > myVersiontoken)
 -          {
 -            // current version is newer than the version that wrote the file
 -            return false;
 -          }
 -          if (supportedVersionToken < myVersiontoken)
 -          {
 -            // current version is older than the version that wrote the file
 -            return true;
 -          }
 -        } 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<JalviewStructureDisplayI> newStructureViewers = null;
                .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)
        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<String, FeatureColourI> featureColours = new Hashtable<String, FeatureColourI>();
+       Map<String, Float> featureOrder = new Hashtable<String, Float>();
  
        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())
          }
          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())
            fdi.setVisible(setting.getType());
          }
        }
-       Hashtable fgtable = new Hashtable();
+       Map<String, Boolean> fgtable = new Hashtable<String, Boolean>();
        for (int gs = 0; gs < jms.getFeatureSettings().getGroupCount(); gs++)
        {
          Group grp = jms.getFeatureSettings().getGroup(gs);
@@@ -26,6 -26,7 +26,7 @@@ import static org.testng.AssertJUnit.as
  import static org.testng.AssertJUnit.assertNull;
  import static org.testng.AssertJUnit.assertTrue;
  
+ import jalview.api.FeatureColourI;
  import jalview.api.FeatureRenderer;
  import jalview.datamodel.Alignment;
  import jalview.datamodel.AlignmentI;
@@@ -33,8 -34,6 +34,6 @@@ import jalview.datamodel.SequenceDummy
  import jalview.datamodel.SequenceFeature;
  import jalview.datamodel.SequenceI;
  import jalview.gui.AlignFrame;
- import jalview.schemes.AnnotationColourGradient;
- import jalview.schemes.GraduatedColor;
  
  import java.awt.Color;
  import java.io.File;
@@@ -54,7 -53,7 +53,7 @@@ public class FeaturesFileTes
      File f = new File("examples/uniref50.fa");
      AlignmentI al = readAlignmentFile(f);
      AlignFrame af = new AlignFrame(al, 500, 500);
-     Map<String, Object> colours = af.getFeatureRenderer()
+     Map<String, FeatureColourI> colours = af.getFeatureRenderer()
              .getFeatureColours();
      FeaturesFile featuresFile = new FeaturesFile(
              "examples/exampleFeatures.txt", FormatAdapter.FILE);
       */
      colours = af.getFeatureRenderer().getFeatureColours();
      assertEquals("26 feature group colours not found", 26, colours.size());
-     assertEquals(colours.get("Cath"), new Color(0x93b1d1));
-     assertEquals(colours.get("ASX-MOTIF"), new Color(0x6addbb));
+     assertEquals(colours.get("Cath").getColour(), new Color(0x93b1d1));
+     assertEquals(colours.get("ASX-MOTIF").getColour(), new Color(0x6addbb));
  
      /*
       * verify (some) features on sequences
       */
      SequenceFeature[] sfs = al.getSequenceAt(0).getDatasetSequence()
              .getSequenceFeatures(); // FER_CAPAA
 -    assertEquals(7, sfs.length);
 +    assertEquals(8, sfs.length);
      SequenceFeature sf = sfs[0];
 +    assertEquals("Pfam family%LINK%", sf.description);
 +    assertEquals(0, sf.begin);
 +    assertEquals(0, sf.end);
 +    assertEquals("uniprot", sf.featureGroup);
 +    assertEquals("Pfam", sf.type);
 +    assertEquals(1, sf.links.size());
 +    assertEquals("Pfam family|http://pfam.xfam.org/family/PF00111",
 +            sf.links.get(0));
 +
 +    sf = sfs[1];
      assertEquals("Iron-sulfur (2Fe-2S)", sf.description);
      assertEquals(39, sf.begin);
      assertEquals(39, sf.end);
      assertEquals("uniprot", sf.featureGroup);
      assertEquals("METAL", sf.type);
 -    sf = sfs[1];
 +    sf = sfs[2];
      assertEquals("Iron-sulfur (2Fe-2S)", sf.description);
      assertEquals(44, sf.begin);
      assertEquals(44, sf.end);
      assertEquals("uniprot", sf.featureGroup);
      assertEquals("METAL", sf.type);
 -    sf = sfs[2];
 +    sf = sfs[3];
      assertEquals("Iron-sulfur (2Fe-2S)", sf.description);
      assertEquals(47, sf.begin);
      assertEquals(47, sf.end);
      assertEquals("uniprot", sf.featureGroup);
      assertEquals("METAL", sf.type);
 -    sf = sfs[3];
 +    sf = sfs[4];
      assertEquals("Iron-sulfur (2Fe-2S)", sf.description);
      assertEquals(77, sf.begin);
      assertEquals(77, sf.end);
      assertEquals("uniprot", sf.featureGroup);
      assertEquals("METAL", sf.type);
 -    sf = sfs[4];
 +    sf = sfs[5];
      assertEquals("Fer2 Status: True Positive Pfam 8_8%LINK%",
              sf.description);
 -    assertEquals("Pfam 8_8|http://pfam.sanger.ac.uk/family/PF00111",
 -            sf.links.get(0).toString());
 +    assertEquals("Pfam 8_8|http://pfam.xfam.org/family/PF00111",
 +            sf.links.get(0));
      assertEquals(8, sf.begin);
      assertEquals(83, sf.end);
      assertEquals("uniprot", sf.featureGroup);
      assertEquals("Pfam", sf.type);
 -    sf = sfs[5];
 +    sf = sfs[6];
      assertEquals("Ferredoxin_fold Status: True Positive ", sf.description);
      assertEquals(3, sf.begin);
      assertEquals(93, sf.end);
      assertEquals("uniprot", sf.featureGroup);
      assertEquals("Cath", sf.type);
 -    sf = sfs[6];
 +    sf = sfs[7];
      assertEquals(
              "High confidence server. Only hits with scores over 0.8 are reported. PHOSPHORYLATION (T) 89_8%LINK%",
              sf.description);
      assertEquals(
              "PHOSPHORYLATION (T) 89_8|http://www.cbs.dtu.dk/cgi-bin/proview/webface-link?seqid=P83527&amp;service=NetPhos-2.0",
 -            sf.links.get(0).toString());
 +            sf.links.get(0));
      assertEquals(89, sf.begin);
      assertEquals(89, sf.end);
      assertEquals("netphos", sf.featureGroup);
      File f = new File("examples/uniref50.fa");
      AlignmentI al = readAlignmentFile(f);
      AlignFrame af = new AlignFrame(al, 500, 500);
-     Map<String, Object> colours = af.getFeatureRenderer()
+     Map<String, FeatureColourI> colours = af.getFeatureRenderer()
              .getFeatureColours();
      // GFF2 uses space as name/value separator in column 9
      String gffData = "METAL\tcc9900\n" + "GFF\n"
      // verify colours read or synthesized
      colours = af.getFeatureRenderer().getFeatureColours();
      assertEquals("1 feature group colours not found", 1, colours.size());
-     assertEquals(colours.get("METAL"), new Color(0xcc9900));
+     assertEquals(colours.get("METAL").getColour(), new Color(0xcc9900));
  
      // verify feature on FER_CAPAA
      SequenceFeature[] sfs = al.getSequenceAt(0).getDatasetSequence()
    }
  
    /**
-    * Test various ways of describing a feature colour scheme
-    * 
-    * @throws Exception
-    */
-   @Test(groups = { "Functional" })
-   public void testParseGraduatedColourScheme() throws Exception
-   {
-     FeaturesFile ff = new FeaturesFile();
-     // colour by label:
-     GraduatedColor gc = ff.parseGraduatedColourScheme(
-             "BETA-TURN-IR\t9a6a94", "label");
-     assertTrue(gc.isColourByLabel());
-     assertEquals(Color.white, gc.getMinColor());
-     assertEquals(Color.black, gc.getMaxColor());
-     assertTrue(gc.isAutoScale());
-     // using colour name, rgb, etc:
-     String spec = "blue|255,0,255|absolute|20.0|95.0|below|66.0";
-     gc = ff.parseGraduatedColourScheme("BETA-TURN-IR\t" + spec, spec);
-     assertFalse(gc.isColourByLabel());
-     assertEquals(Color.blue, gc.getMinColor());
-     assertEquals(new Color(255, 0, 255), gc.getMaxColor());
-     assertFalse(gc.isAutoScale());
-     assertFalse(gc.getTolow());
-     assertEquals(20.0f, gc.getMin(), 0.001f);
-     assertEquals(95.0f, gc.getMax(), 0.001f);
-     assertEquals(AnnotationColourGradient.BELOW_THRESHOLD,
-             gc.getThreshType());
-     assertEquals(66.0f, gc.getThresh(), 0.001f);
-     // inverse gradient high to low:
-     spec = "blue|255,0,255|95.0|20.0|below|66.0";
-     gc = ff.parseGraduatedColourScheme("BETA-TURN-IR\t" + spec, spec);
-     assertTrue(gc.isAutoScale());
-     assertTrue(gc.getTolow());
-   }
-   /**
     * Test parsing a features file with GFF formatted content only
     * 
     * @throws Exception
      File f = new File("examples/uniref50.fa");
      AlignmentI al = readAlignmentFile(f);
      AlignFrame af = new AlignFrame(al, 500, 500);
-     Map<String, Object> colours = af.getFeatureRenderer()
+     Map<String, FeatureColourI> colours = af.getFeatureRenderer()
              .getFeatureColours();
      // GFF3 uses '=' separator for name/value pairs in colum 9
      String gffData = "##gff-version 3\n"
      File f = new File("examples/uniref50.fa");
      AlignmentI al = readAlignmentFile(f);
      AlignFrame af = new AlignFrame(al, 500, 500);
-     Map<String, Object> colours = af.getFeatureRenderer()
+     Map<String, FeatureColourI> colours = af.getFeatureRenderer()
              .getFeatureColours();
  
      /*
      File f = new File("examples/uniref50.fa");
      AlignmentI al = readAlignmentFile(f);
      AlignFrame af = new AlignFrame(al, 500, 500);
-     Map<String, Object> colours = af.getFeatureRenderer()
+     Map<String, FeatureColourI> colours = af.getFeatureRenderer()
              .getFeatureColours();
      String features = "METAL\tcc9900\n"
              + "GAMMA-TURN\tred|0,255,255|20.0|95.0|below|66.0\n"
              + "STARTGROUP\tuniprot\n"
              + "Iron\tFER_CAPAA\t-1\t39\t39\tMETAL\n"
              + "Turn\tFER_CAPAA\t-1\t36\t38\tGAMMA-TURN\n"
 -            + "<html>Pfam domain<a href=\"http://pfam.sanger.ac.uk/family/PF00111\">Pfam_3_4</a></html>\tFER_CAPAA\t-1\t20\t20\tPfam\n"
 +            + "<html>Pfam domain<a href=\"http://pfam.xfam.org/family/PF00111\">Pfam_3_4</a></html>\tFER_CAPAA\t-1\t20\t20\tPfam\n"
              + "ENDGROUP\tuniprot\n";
      FeaturesFile featuresFile = new FeaturesFile(features,
              FormatAdapter.PASTE);
       * first with no features displayed
       */
      FeatureRenderer fr = af.alignPanel.getFeatureRenderer();
-     Map<String, Object> visible = fr
+     Map<String, FeatureColourI> visible = fr
              .getDisplayedFeatureCols();
      String exported = featuresFile.printJalviewFormat(
              al.getSequencesArray(), visible);
              + "\nSTARTGROUP\tuniprot\n"
              + "Iron\tFER_CAPAA\t-1\t39\t39\tMETAL\t0.0\n"
              + "Turn\tFER_CAPAA\t-1\t36\t38\tGAMMA-TURN\t0.0\n"
 -            + "<html>Pfam domain<a href=\"http://pfam.sanger.ac.uk/family/PF00111\">Pfam_3_4</a></html>\tFER_CAPAA\t-1\t20\t20\tPfam\t0.0\n"
 +            + "<html>Pfam domain<a href=\"http://pfam.xfam.org/family/PF00111\">Pfam_3_4</a></html>\tFER_CAPAA\t-1\t20\t20\tPfam\t0.0\n"
              + "ENDGROUP\tuniprot\n";
      assertEquals(expected, exported);
    }