JAL-1479 added support for SIFTs mapping output viewing and implemented exception...
authortcofoegbu <tcnofoegbu@dundee.ac.uk>
Wed, 28 Oct 2015 11:48:20 +0000 (11:48 +0000)
committertcofoegbu <tcnofoegbu@dundee.ac.uk>
Wed, 28 Oct 2015 11:48:20 +0000 (11:48 +0000)
src/jalview/api/DBRefEntryI.java
src/jalview/api/SiftsClientI.java
src/jalview/datamodel/DBRefEntry.java
src/jalview/structure/StructureSelectionManager.java
src/jalview/ws/sifts/MappingOutputPojo.java [new file with mode: 0644]
src/jalview/ws/sifts/SiftsClient.java
src/jalview/ws/sifts/SiftsException.java [new file with mode: 0644]
test/jalview/ws/sifts/SiftsClientTest.java

index 3238781..b927fa5 100644 (file)
@@ -5,23 +5,68 @@ public interface DBRefEntryI
 {
   public boolean equalRef(DBRefEntryI entry);
 
+  /**
+   * 
+   * @return Source DB name for this entry
+   */
   public String getSource();
 
-  public String getVersion();
-
+  /**
+   * 
+   * @return Accession Id for this entry
+   */
   public String getAccessionId();
 
+  /**
+   * 
+   * @param accessionId
+   *          Accession Id for this entry
+   */
   public void setAccessionId(String accessionId);
 
+  /**
+   * 
+   * @param source
+   *          Source DB name for this entry
+   */
   public void setSource(String source);
 
+  /**
+   * 
+   * @return Source DB version for this entry
+   */
+  public String getVersion();
+
+  /**
+   * 
+   * @param version
+   *          Source DB version for this entry
+   */
   public void setVersion(String version);
 
+  /**
+   * 
+   * @param startRes
+   *          index of start residue in the source DB
+   */
   public void setStartRes(int startRes);
 
+  /**
+   * 
+   * @return index of start residue in the source DB
+   */
   public int getStartRes();
 
+  /**
+   * 
+   * @param endRes
+   *          index of end residue in the source DB
+   */
   public void setEndRes(int endRes);
 
+  /**
+   * 
+   * @return index of end residue in the source DB
+   */
   public int getEndRes();
 }
index 13223af..8a246e1 100644 (file)
@@ -22,6 +22,8 @@ package jalview.api;
 
 import jalview.datamodel.SequenceI;
 import jalview.structure.StructureMapping;
+import jalview.ws.sifts.MappingOutputPojo;
+import jalview.ws.sifts.SiftsException;
 import jalview.xml.binding.sifts.Entry.Entity;
 
 import java.util.HashSet;
@@ -78,7 +80,7 @@ public interface SiftsClientI
    * @return Entity
    * @throws Exception
    */
-  public Entity getEntityById(String id) throws Exception;
+  public Entity getEntityById(String id) throws SiftsException;
 
   /**
    * Get all accession Ids available in the current SIFTs entry
@@ -103,27 +105,12 @@ public interface SiftsClientI
   public String[] getEntryDBs();
 
   /**
-   * Get the SIFTs Entry details
-   */
-  public void getEntryDetails();
-
-  /**
    * 
-   * @param seq1
-   *          Sequence to map
-   * @param seq2
-   *          Structure Sequence
-   * @param seqID1
-   *          sequence id
-   * @param seqID2
-   *          structure sequence id
-   * @param seqType
-   *          type of sequence for the mapping (pep or protein)
-   * @param nochunks
-   * @return sequence->structure mapping as int [][]
+   * @param mop
+   *          MappingOutputPojo
+   * @return Sequence<->Structure mapping as int[][]
    */
-  public StringBuffer getMappingOutput(String seq1, String seq2,
-          String seqID1, String seqID2, String seqType, int nochunks);
+  public StringBuffer getMappingOutput(MappingOutputPojo mop);
 
   /**
    * 
@@ -134,9 +121,10 @@ public interface SiftsClientI
    * @param chain
    *          the chain of the entry to use for mapping
    * @return StructureMapping
+   * @throws SiftsException
    */
-  public StructureMapping getSiftsStructureMapping(SequenceI seq, String pdbFile,
-          String chain);
+  public StructureMapping getSiftsStructureMapping(SequenceI seq,
+          String pdbFile, String chain) throws SiftsException;
   
   /**
    * Get residue by residue mapping for a given Sequence and SIFTs entity
@@ -149,5 +137,5 @@ public interface SiftsClientI
    * @throws Exception
    */
   public int[][] getGreedyMapping(String entityId, SequenceI seq,
-          java.io.PrintStream os) throws Exception;
+          java.io.PrintStream os) throws SiftsException;
 }
\ No newline at end of file
index 142d996..0b1fb6d 100755 (executable)
@@ -143,39 +143,28 @@ public class DBRefEntry implements DBRefEntryI
     return accessionId;
   }
 
-  /**
-   * @param accessionId
-   *          the accessionId to set
-   */
+
   @Override
   public void setAccessionId(String accessionId)
   {
     this.accessionId = accessionId;
   }
 
-  /**
-   * @param source
-   *          the source to set
-   */
+
   @Override
   public void setSource(String source)
   {
     this.source = source;
   }
 
-  /**
-   * @param version
-   *          the version to set
-   */
+
   @Override
   public void setVersion(String version)
   {
     this.version = version;
   }
 
-  /**
-   * @return the map
-   */
+
   public Mapping getMap()
   {
     return map;
@@ -211,21 +200,25 @@ public class DBRefEntry implements DBRefEntryI
     return getSrcAccString();
   }
 
+  @Override
   public int getStartRes()
   {
     return startRes;
   }
 
+  @Override
   public void setStartRes(int startRes)
   {
     this.startRes = startRes;
   }
 
+  @Override
   public int getEndRes()
   {
     return endRes;
   }
 
+  @Override
   public void setEndRes(int endRes)
   {
     this.endRes = endRes;
index 38e7db3..846ec9c 100644 (file)
@@ -503,6 +503,8 @@ public class StructureSelectionManager
           AlignSeq maxAlignseq)
   {
     final StringBuilder mappingDetails = new StringBuilder(128);
+    mappingDetails.append(NEWLINE).append(
+            "Sequence \u27f7 Structure mapping details");
     mappingDetails.append(NEWLINE).append("PDB Sequence is :")
             .append(NEWLINE).append("Sequence = ")
             .append(maxChain.sequence.getSequenceAsString());
diff --git a/src/jalview/ws/sifts/MappingOutputPojo.java b/src/jalview/ws/sifts/MappingOutputPojo.java
new file mode 100644 (file)
index 0000000..c06e51f
--- /dev/null
@@ -0,0 +1,129 @@
+package jalview.ws.sifts;
+
+public class MappingOutputPojo
+{
+  private String seqName;
+
+  private String seqResidue;
+
+  private int seqStart;
+
+  private int seqEnd;
+
+  private String strName;
+
+  private String strResidue;
+
+  private int strStart;
+
+  private int strEnd;
+
+  private String type;
+
+  private int wrapHeight;
+
+  private static final int MAX_ID_LENGTH = 30;
+
+  public String getSeqName()
+  {
+    return seqName;
+  }
+
+  public void setSeqName(String seqName)
+  {
+    this.seqName = (seqName.length() > MAX_ID_LENGTH) ? seqName.substring(
+            0, MAX_ID_LENGTH) : seqName;
+  }
+
+  public String getSeqResidue()
+  {
+    return seqResidue;
+  }
+
+  public void setSeqResidue(String seqResidue)
+  {
+    this.seqResidue = seqResidue;
+  }
+
+  public int getSeqStart()
+  {
+    return seqStart;
+  }
+
+  public void setSeqStart(int seqStart)
+  {
+    this.seqStart = seqStart;
+  }
+
+  public int getSeqEnd()
+  {
+    return seqEnd;
+  }
+
+  public void setSeqEnd(int seqEnd)
+  {
+    this.seqEnd = seqEnd;
+  }
+
+  public String getStrName()
+  {
+    return strName;
+  }
+
+  public void setStrName(String strName)
+  {
+    this.strName = (strName.length() > MAX_ID_LENGTH) ? strName.substring(
+            0, MAX_ID_LENGTH) : strName;
+  }
+
+  public String getStrResidue()
+  {
+    return strResidue;
+  }
+
+  public void setStrResidue(String strResidue)
+  {
+    this.strResidue = strResidue;
+  }
+
+  public int getStrStart()
+  {
+    return strStart;
+  }
+
+  public void setStrStart(int strStart)
+  {
+    this.strStart = strStart;
+  }
+
+  public int getStrEnd()
+  {
+    return strEnd;
+  }
+
+  public void setStrEnd(int strEnd)
+  {
+    this.strEnd = strEnd;
+  }
+
+  public String getType()
+  {
+    return type;
+  }
+
+  public void setType(String type)
+  {
+    this.type = type;
+  }
+
+  public int getWrapHeight()
+  {
+    return wrapHeight;
+  }
+
+  public void setWrapHeight(int wrapHeight)
+  {
+    this.wrapHeight = wrapHeight;
+  }
+
+}
index bde215d..176c511 100644 (file)
@@ -18,7 +18,7 @@
  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
  * The Jalview Authors are detailed in the 'AUTHORS' file.
  */
-package jalview.io;
+package jalview.ws.sifts;
 
 import jalview.analysis.AlignSeq;
 import jalview.api.DBRefEntryI;
@@ -34,7 +34,6 @@ import jalview.xml.binding.sifts.Entry.Entity.Segment;
 import jalview.xml.binding.sifts.Entry.Entity.Segment.ListMapRegion.MapRegion;
 import jalview.xml.binding.sifts.Entry.Entity.Segment.ListResidue.Residue;
 import jalview.xml.binding.sifts.Entry.Entity.Segment.ListResidue.Residue.CrossRefDb;
-import jalview.xml.binding.sifts.Entry.EntryDetail;
 import jalview.xml.binding.sifts.Entry.ListDB.Db;
 
 import java.io.File;
@@ -46,8 +45,9 @@ import java.io.InputStream;
 import java.io.PrintStream;
 import java.net.URL;
 import java.net.URLConnection;
-import java.util.HashMap;
+import java.util.ArrayList;
 import java.util.HashSet;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.zip.GZIPInputStream;
 
@@ -65,6 +65,10 @@ public class SiftsClient implements SiftsClientI
 
   private String pdbId;
 
+  private String structId;
+
+  private String segStartEnd;
+
   private static final int BUFFER_SIZE = 4096;
 
   private static final String SIFTS_FTP_BASE_URL = "ftp://ftp.ebi.ac.uk/pub/databases/msd/sifts/xml/";
@@ -248,7 +252,8 @@ public class SiftsClient implements SiftsClientI
    * @throws Exception
    *           if no valid source DBRefEntry was found for the given sequences
    */
-  public DBRefEntryI getValidSourceDBRef(SequenceI seq) throws Exception
+  public DBRefEntryI getValidSourceDBRef(SequenceI seq)
+          throws SiftsException
   {
     DBRefEntryI sourceDBRef = null;
     sourceDBRef = seq.getSourceDBRef();
@@ -269,7 +274,7 @@ public class SiftsClient implements SiftsClientI
 
       if (dbRefs == null || dbRefs.length < 1)
       {
-        throw new Exception("Could not get source DB Ref");
+        throw new SiftsException("Could not get source DB Ref");
       }
 
       for (DBRefEntryI dbRef : dbRefs)
@@ -291,7 +296,7 @@ public class SiftsClient implements SiftsClientI
     {
       return sourceDBRef;
     }
-    throw new Exception("Could not get source DB Ref");
+    throw new SiftsException("Could not get source DB Ref");
   }
 
 
@@ -331,44 +336,80 @@ public class SiftsClient implements SiftsClientI
     return accessions;
   }
 
+  @Override
+  public StructureMapping getSiftsStructureMapping(SequenceI seq,
+          String pdbFile, String chain) throws SiftsException
+  {
+    structId = (chain == null) ? pdbId : pdbId + "|" + chain;
+    System.out.println("Getting mapping for: " + pdbId + "|" + chain
+            + " : seq- " + seq.getName());
+
+    final StringBuilder mappingDetails = new StringBuilder(128);
+    PrintStream ps = new PrintStream(System.out)
+    {
+      @Override
+      public void print(String x)
+      {
+        mappingDetails.append(x);
+      }
+
+      @Override
+      public void println()
+      {
+        mappingDetails.append(NEWLINE);
+      }
+    };
+    int[][] mapping = getGreedyMapping(chain, seq, ps);
+
+    String mappingOutput = mappingDetails.toString();
+    return new StructureMapping(seq, pdbFile, pdbId, chain, mapping,
+            mappingOutput);
+  }
 
   @Override
   public int[][] getGreedyMapping(String entityId, SequenceI seq,
           java.io.PrintStream os)
-          throws Exception
+ throws SiftsException
   {
+    int matchedResStart = -1;
+    int matchedResEnd = -1;
+    int counter = 0;
+    int pdbStart = -1;
+    int pdbEnd = -1;
+    int sStart = -1;
+    int sEnd = -1;
+    boolean startDetected = false;
+
     System.out.println("Generating mappings for : " + entityId);
     Entity entity = null;
     entity = getEntityById(entityId);
     String seqStr = AlignSeq.extractGaps(jalview.util.Comparison.GapChars,
             seq.getSequenceAsString());
-    // StringBuilder mappedStrucSeq = new StringBuilder(seqStr.length());
-    String[] mappedStrucSeq = new String[seqStr.length()];
-    int mapping[][] = new int[seqStr.length()][2];
+    int mapping[][] = new int[seqStr.length() + seq.getStart()][2];
     DBRefEntryI sourceDBRef = seq.getSourceDBRef();
     if (sourceDBRef == null)
     {
       sourceDBRef = getValidSourceDBRef(seq);
-      // TODO if sourceDBRef is null at this point then throw an Exception
-
       // TODO update sequence start/end with sourceDBRef start/end
       // seq.setStart(sourceDBRef.getStartRes());
       // seq.setEnd(sourceDBRef.getEndRes());
     }
 
     String crossRefAccessionId = sourceDBRef.getAccessionId();
-    int start = seq.getStart() - 1;
+    int count = 0;
     for (int residue[] : mapping)
     {
-      residue[1] = start++;
+      residue[1] = count++;
+      residue[0] = -1;
     }
     
-    HashMap<Integer, String> resNumMap = new HashMap<Integer, String>();
+    LinkedHashMap<Integer, String> resNumMap = new LinkedHashMap<Integer, String>();
     List<Segment> segments = entity.getSegment();
     for (Segment segment : segments)
     {
+      segStartEnd = segment.getStart() + " - " + segment.getEnd();
       System.out.println("Mappging segments : " + segment.getSegId() + "\\"
-              + segment.getStart() + "-" + segment.getEnd());
+              + segStartEnd);
       List<Residue> residues = segment.getListResidue().getResidue();
       for (Residue residue : residues)
       {
@@ -386,42 +427,84 @@ public class SiftsClient implements SiftsClientI
         {
           continue;
         }
+        int loopCount = 0;
         for (int[] x : mapping)
         {
-          if (x[1] == refDbResNum)
+          if (loopCount > seq.getStart() && x[1] == refDbResNum)
           {
             int resNum = Integer.valueOf(residue.getDbResNum());
             x[0] = resNum;
-            String value = "x";
-            resNumMap.put(resNum, value);
+            char resCharCode = ResidueProperties
+                    .getSingleCharacterCode(residue.getDbResName());
+            resNumMap.put(resNum, String.valueOf(resCharCode));
           }
+          ++loopCount;
         }
       }
     }
-    
-    //Generate visual mapping output
-    // StringBuilder strucSeq = new StringBuilder();
-    // for(int[] x : mapping){
-      // if(mapping[0] == 0){
-      // strucSeq.append(b)
-      // }
-    // }
-    mappedStrucSeq[1] = "x";
+
+    for (int[] x : mapping)
+    {
+      if (!startDetected && x[0] > -1)
+      {
+        matchedResStart = counter;
+        // System.out.println(matchedResStart);
+        startDetected = true;
+      }
+
+      if (startDetected && x[0] == -1)
+      {
+        matchedResEnd = counter;
+      }
+      ++counter;
+    }
+
+    String matchedSeqStr = seqStr;
+    if (matchedResStart != -1)
+    {
+      matchedResEnd = (matchedResEnd == -1) ? counter : matchedResEnd;
+      pdbStart = mapping[matchedResStart][0];
+      pdbEnd = mapping[matchedResEnd - 1][0];
+      sStart = mapping[matchedResStart][1];
+      sEnd = mapping[matchedResEnd - 1][1];
+      int seqStart = seq.getStart();
+      if (seqStart > 1)
+      {
+        matchedResStart = matchedResStart - seqStart;
+        matchedResEnd = matchedResEnd - seqStart;
+      }
+      else
+      {
+        --matchedResStart;
+        --matchedResEnd;
+      }
+      matchedSeqStr = seqStr.substring(matchedResStart, matchedResEnd);
+    }
+
+    StringBuilder targetStrucSeqs = new StringBuilder();
+    for (String res : resNumMap.values())
+    {
+      targetStrucSeqs.append(res);
+    }
+
     try
     {
-      System.out.println(">>>> seq: " + seqStr + "\nlength "
-              + seqStr.length());
-      System.out.println(">>>> pdb: " + mappedStrucSeq.toString()
-              + "\nlength " + mappedStrucSeq.toString().length());
-
-      String printedMapping = getMappingOutput(mappedStrucSeq.toString(),
-              seqStr, "seqAccession", "strucAccession", "pep", 3)
-              .toString();
       if (os != null)
       {
-        os.print(printedMapping);
+        MappingOutputPojo mop = new MappingOutputPojo();
+        mop.setSeqStart(sStart);
+        mop.setSeqEnd(sEnd);
+        mop.setSeqName(seq.getName());
+        mop.setSeqResidue(matchedSeqStr);
+
+        mop.setStrStart(pdbStart);
+        mop.setStrEnd(pdbEnd);
+        mop.setStrName(structId);
+        mop.setStrResidue(targetStrucSeqs.toString());
+
+        mop.setType("pep");
+        os.print(getMappingOutput(mop).toString());
       }
-      System.out.println();
     } catch (Exception ex)
     {
       ex.printStackTrace();
@@ -436,44 +519,9 @@ public class SiftsClient implements SiftsClientI
             && getAllMappingAccession().contains(accessionId);
   }
 
-  @Override
-  public StructureMapping getSiftsStructureMapping(SequenceI seq,
-          String pdbFile, String chain)
-  {
-    System.out.println("Getting mapping for: " + pdbId + "|" + chain
-            + " : seq- " + seq.getName());
-
-    final StringBuilder mappingDetails = new StringBuilder(128);
-    PrintStream ps = new PrintStream(System.out)
-    {
-      @Override
-      public void print(String x)
-      {
-        mappingDetails.append(x);
-      }
-
-      @Override
-      public void println()
-      {
-        mappingDetails.append(NEWLINE);
-      }
-    };
-    int[][] mapping = null;
-    try
-    {
-      mapping = getGreedyMapping(chain, seq, ps);
-    } catch (Exception e)
-    {
-      e.printStackTrace();
-    }
-    // String mappingOutput = mappingDetails.toString();
-    String mappingOutput = null;
-    return new StructureMapping(seq, pdbFile, pdbId, chain, mapping,
-            mappingOutput);
-  }
 
   @Override
-  public Entity getEntityById(String id) throws Exception
+  public Entity getEntityById(String id) throws SiftsException
   {
     List<Entity> entities = siftsEntry.getEntity();
     for (Entity entity : entities)
@@ -484,52 +532,77 @@ public class SiftsClient implements SiftsClientI
       }
       return entity;
     }
-    throw new Exception("Entity " + id + " not found");
+    throw new SiftsException("Entity " + id + " not found");
   }
 
   @Override
   public String[] getEntryDBs()
   {
     System.out.println("\nListing DB entries...");
+    List<String> availDbs = new ArrayList<String>();
     List<Db> dbs = siftsEntry.getListDB().getDb();
     for (Db db : dbs)
     {
+      availDbs.add(db.getDbSource());
       System.out.println(db.getDbSource() + " | " + db.getDbCoordSys());
     }
-    return null;
-  }
-
-  @Override
-  public void getEntryDetails()
-  {
-    List<EntryDetail> eds = siftsEntry.getEntryDetail();
-    for (EntryDetail ed : eds)
-    {
-      System.out.println("Entry Details: " + ed.getContent() + " "
-              + ed.getDbSource() + " " + ed.getProperty() + " "
-              + ed.toString());
-    }
+    return availDbs.toArray(new String[0]);
   }
 
   @Override
-  public StringBuffer getMappingOutput(String astr1, String astr2, String s1id,
-          String s2id, String type, int nochunks)
+  public StringBuffer getMappingOutput(MappingOutputPojo mp)
   {
-    int maxid = s1id.length();
+    String seqRes = mp.getSeqResidue();
+    String seqName = mp.getSeqName();
+    int sStart = mp.getSeqStart();
+    int sEnd = mp.getSeqEnd();
+
+    String strRes = mp.getStrResidue();
+    String strName = mp.getStrName();
+    int pdbStart = mp.getStrStart();
+    int pdbEnd = mp.getStrEnd();
+    
+    String type = mp.getType();
+    
+    int maxid = (seqName.length() >= strName.length()) ? seqName.length()
+            : strName.length();
     int len = 72 - maxid - 1;
-    StringBuffer output = new StringBuffer();
+
+    // int nochunks = 2;// mp.getWrapHeight();
+    int nochunks = ((seqRes.length()) / len)
+            + ((seqRes.length()) % len > 0 ? 1 : 0);
     // output mappings
+    StringBuffer output = new StringBuffer();
+    output.append(NEWLINE);
+    output.append("Sequence ⟷ Structure mapping details:");
+    output.append(NEWLINE).append(NEWLINE);
+
+    output.append(new Format("%" + maxid + "s").form(seqName));
+    output.append(" :  ");
+    output.append(String.valueOf(sStart));
+    output.append(" - ");
+    output.append(String.valueOf(sEnd));
+    output.append(" Maps to ");
+    output.append(NEWLINE);
+    output.append(new Format("%" + maxid + "s").form(structId));
+    output.append(" :  ");
+    output.append(String.valueOf(pdbStart));
+    output.append(" - ");
+    output.append(String.valueOf(pdbEnd));
+    output.append(NEWLINE).append(NEWLINE);
+    
     float pid = 0;
     for (int j = 0; j < nochunks; j++)
     {
       // Print the first aligned sequence
-      output.append(new Format("%" + (maxid) + "s").form(s1id)).append(" ");
+      output.append(new Format("%" + (maxid) + "s").form(seqName)).append(
+              " ");
 
       for (int i = 0; i < len; i++)
       {
-        if ((i + (j * len)) < astr1.length())
+        if ((i + (j * len)) < seqRes.length())
         {
-          output.append(astr1.charAt(i + (j * len)));
+          output.append(seqRes.charAt(i + (j * len)));
         }
       }
 
@@ -539,10 +612,10 @@ public class SiftsClient implements SiftsClientI
       // Print out the matching chars
       for (int i = 0; i < len; i++)
       {
-        if ((i + (j * len)) < astr1.length())
+        if ((i + (j * len)) < seqRes.length())
         {
-          if (astr1.charAt(i + (j * len)) == astr2.charAt(i + (j * len))
-                  && !jalview.util.Comparison.isGap(astr1.charAt(i
+          if (seqRes.charAt(i + (j * len)) == strRes.charAt(i + (j * len))
+                  && !jalview.util.Comparison.isGap(seqRes.charAt(i
                           + (j * len))))
           {
             pid++;
@@ -550,8 +623,8 @@ public class SiftsClient implements SiftsClientI
           }
           else if (type.equals("pep"))
           {
-            if (ResidueProperties.getPAM250(astr1.charAt(i + (j * len)),
-                    astr2.charAt(i + (j * len))) > 0)
+            if (ResidueProperties.getPAM250(seqRes.charAt(i + (j * len)),
+                    strRes.charAt(i + (j * len))) > 0)
             {
               output.append(".");
             }
@@ -568,21 +641,23 @@ public class SiftsClient implements SiftsClientI
       }
       // Now print the second aligned sequence
       output = output.append(NEWLINE);
-      output = output.append(new Format("%" + (maxid) + "s").form(s2id))
+      output = output.append(new Format("%" + (maxid) + "s").form(strName))
               .append(" ");
       for (int i = 0; i < len; i++)
       {
-        if ((i + (j * len)) < astr2.length())
+        if ((i + (j * len)) < strRes.length())
         {
-          output.append(astr2.charAt(i + (j * len)));
+          output.append(strRes.charAt(i + (j * len)));
         }
       }
       output.append(NEWLINE).append(NEWLINE);
     }
-    pid = pid / (astr1.length()) * 100;
-    System.out.println(output);
-    System.out.println(pid);
-    // TODO return output & pid
+    pid = pid / (seqRes.length()) * 100;
+    output.append("Length of alignment = " + seqRes.length())
+            .append(NEWLINE);
+    output.append(new Format("Percentage ID = %2.2f").form(pid));
+    output.append(NEWLINE);
+    output.append("Mapping method: SIFTS").append(NEWLINE);
     return output;
   }
   
diff --git a/src/jalview/ws/sifts/SiftsException.java b/src/jalview/ws/sifts/SiftsException.java
new file mode 100644 (file)
index 0000000..2923541
--- /dev/null
@@ -0,0 +1,12 @@
+package jalview.ws.sifts;
+
+public class SiftsException extends Exception
+{
+
+  private static final long serialVersionUID = 1L;
+
+  public SiftsException(String message)
+  {
+    super(message);
+  }
+}
index 6ff3705..dab7f12 100644 (file)
@@ -18,7 +18,7 @@
  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
  * The Jalview Authors are detailed in the 'AUTHORS' file.
  */
-package jalview.io;
+package jalview.ws.sifts;
 
 import jalview.datamodel.DBRefEntry;
 import jalview.datamodel.Sequence;
@@ -48,34 +48,36 @@ public class SiftsClientTest
                   + "AYKVTLVTPTGNVEFQCPDDVYILDAAEEEGIDLPYSCRAGSCSSCAGKLKTGSLNQDD"
                   + "QSFLDDDQIDEGWVLTCAAYPVSDVTIETHKEEELTA.", 1, 147);
 
-  int[][] expectedMapping = { { 0, 0 }, { 0, 1 }, { 0, 2 }, { 0, 3 },
-      { 0, 4 }, { 0, 5 }, { 0, 6 }, { 0, 7 }, { 0, 8 }, { 0, 9 },
-      { 0, 10 }, { 0, 11 }, { 0, 12 }, { 0, 13 }, { 0, 14 }, { 0, 15 },
-      { 0, 16 }, { 0, 17 }, { 0, 18 }, { 0, 19 }, { 0, 20 }, { 0, 21 },
-      { 0, 22 }, { 0, 23 }, { 0, 24 }, { 0, 25 }, { 0, 26 }, { 0, 27 },
-      { 0, 28 }, { 0, 29 }, { 0, 30 }, { 0, 31 }, { 0, 32 }, { 0, 33 },
-      { 0, 34 }, { 0, 35 }, { 0, 36 }, { 0, 37 }, { 0, 38 }, { 0, 39 },
-      { 0, 40 }, { 0, 41 }, { 0, 42 }, { 0, 43 }, { 0, 44 }, { 0, 45 },
-      { 0, 46 }, { 0, 47 }, { 0, 48 }, { 0, 49 }, { 0, 50 }, { 1, 51 },
-      { 2, 52 }, { 3, 53 }, { 4, 54 }, { 5, 55 }, { 6, 56 }, { 7, 57 },
-      { 8, 58 }, { 9, 59 }, { 10, 60 }, { 11, 61 }, { 12, 62 }, { 13, 63 },
-      { 14, 64 }, { 15, 65 }, { 16, 66 }, { 17, 67 }, { 18, 68 },
-      { 19, 69 }, { 20, 70 }, { 21, 71 }, { 22, 72 }, { 23, 73 },
-      { 24, 74 }, { 25, 75 }, { 26, 76 }, { 27, 77 }, { 28, 78 },
-      { 29, 79 }, { 30, 80 }, { 31, 81 }, { 32, 82 }, { 33, 83 },
-      { 34, 84 }, { 35, 85 }, { 36, 86 }, { 37, 87 }, { 38, 88 },
-      { 39, 89 }, { 40, 90 }, { 41, 91 }, { 42, 92 }, { 43, 93 },
-      { 44, 94 }, { 45, 95 }, { 46, 96 }, { 47, 97 }, { 48, 98 },
-      { 49, 99 }, { 50, 100 }, { 51, 101 }, { 52, 102 }, { 53, 103 },
-      { 54, 104 }, { 55, 105 }, { 56, 106 }, { 57, 107 }, { 58, 108 },
-      { 59, 109 }, { 60, 110 }, { 61, 111 }, { 62, 112 }, { 63, 113 },
-      { 64, 114 }, { 65, 115 }, { 66, 116 }, { 67, 117 }, { 68, 118 },
-      { 69, 119 }, { 70, 120 }, { 71, 121 }, { 72, 122 }, { 73, 123 },
-      { 74, 124 }, { 75, 125 }, { 76, 126 }, { 77, 127 }, { 78, 128 },
-      { 79, 129 }, { 80, 130 }, { 81, 131 }, { 82, 132 }, { 83, 133 },
-      { 84, 134 }, { 85, 135 }, { 86, 136 }, { 87, 137 }, { 88, 138 },
-      { 89, 139 }, { 90, 140 }, { 91, 141 }, { 92, 142 }, { 93, 143 },
-      { 94, 144 }, { 95, 145 }, { 96, 146 } };
+  int[][] expectedMapping = { { -1, 0 }, { -1, 1 }, { -1, 2 }, { -1, 3 },
+      { -1, 4 }, { -1, 5 }, { -1, 6 }, { -1, 7 }, { -1, 8 }, { -1, 9 },
+      { -1, 10 }, { -1, 11 }, { -1, 12 }, { -1, 13 }, { -1, 14 },
+      { -1, 15 }, { -1, 16 }, { -1, 17 }, { -1, 18 }, { -1, 19 },
+      { -1, 20 }, { -1, 21 }, { -1, 22 }, { -1, 23 }, { -1, 24 },
+      { -1, 25 }, { -1, 26 }, { -1, 27 }, { -1, 28 }, { -1, 29 },
+      { -1, 30 }, { -1, 31 }, { -1, 32 }, { -1, 33 }, { -1, 34 },
+      { -1, 35 }, { -1, 36 }, { -1, 37 }, { -1, 38 }, { -1, 39 },
+      { -1, 40 }, { -1, 41 }, { -1, 42 }, { -1, 43 }, { -1, 44 },
+      { -1, 45 }, { -1, 46 }, { -1, 47 }, { -1, 48 }, { -1, 49 },
+      { -1, 50 }, { 1, 51 }, { 2, 52 }, { 3, 53 }, { 4, 54 }, { 5, 55 },
+      { 6, 56 }, { 7, 57 }, { 8, 58 }, { 9, 59 }, { 10, 60 }, { 11, 61 },
+      { 12, 62 }, { 13, 63 }, { 14, 64 }, { 15, 65 }, { 16, 66 },
+      { 17, 67 }, { 18, 68 }, { 19, 69 }, { 20, 70 }, { 21, 71 },
+      { 22, 72 }, { 23, 73 }, { 24, 74 }, { 25, 75 }, { 26, 76 },
+      { 27, 77 }, { 28, 78 }, { 29, 79 }, { 30, 80 }, { 31, 81 },
+      { 32, 82 }, { 33, 83 }, { 34, 84 }, { 35, 85 }, { 36, 86 },
+      { 37, 87 }, { 38, 88 }, { 39, 89 }, { 40, 90 }, { 41, 91 },
+      { 42, 92 }, { 43, 93 }, { 44, 94 }, { 45, 95 }, { 46, 96 },
+      { 47, 97 }, { 48, 98 }, { 49, 99 }, { 50, 100 }, { 51, 101 },
+      { 52, 102 }, { 53, 103 }, { 54, 104 }, { 55, 105 }, { 56, 106 },
+      { 57, 107 }, { 58, 108 }, { 59, 109 }, { 60, 110 }, { 61, 111 },
+      { 62, 112 }, { 63, 113 }, { 64, 114 }, { 65, 115 }, { 66, 116 },
+      { 67, 117 }, { 68, 118 }, { 69, 119 }, { 70, 120 }, { 71, 121 },
+      { 72, 122 }, { 73, 123 }, { 74, 124 }, { 75, 125 }, { 76, 126 },
+      { 77, 127 }, { 78, 128 }, { 79, 129 }, { 80, 130 }, { 81, 131 },
+      { 82, 132 }, { 83, 133 }, { 84, 134 }, { 85, 135 }, { 86, 136 },
+      { 87, 137 }, { 88, 138 }, { 89, 139 }, { 90, 140 }, { 91, 141 },
+      { 92, 142 }, { 93, 143 }, { 94, 144 }, { 95, 145 }, { 96, 146 },
+      { 97, 147 } };
 
   @BeforeTest(alwaysRun = true)
   public void setUpSiftsClient()