JAL-2136 New Phyre2 branch + attempt to resynced with develop
[jalview.git] / src / jalview / ws / sifts / SiftsClient.java
index 5825a26..53a2b8c 100644 (file)
@@ -21,6 +21,8 @@
 package jalview.ws.sifts;
 
 import jalview.analysis.AlignSeq;
+import jalview.analysis.scoremodels.ScoreMatrix;
+import jalview.analysis.scoremodels.ScoreModels;
 import jalview.api.DBRefEntryI;
 import jalview.api.SiftsClientI;
 import jalview.datamodel.DBRefEntry;
@@ -29,7 +31,6 @@ import jalview.datamodel.SequenceI;
 import jalview.io.StructureFile;
 import jalview.schemes.ResidueProperties;
 import jalview.structure.StructureMapping;
-import jalview.structure.StructureMappingClient;
 import jalview.structures.models.MappingOutputModel;
 import jalview.util.Comparison;
 import jalview.util.DBRefUtils;
@@ -55,6 +56,7 @@ import java.nio.file.Path;
 import java.nio.file.attribute.BasicFileAttributes;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.Date;
 import java.util.HashMap;
@@ -70,8 +72,10 @@ import javax.xml.bind.Unmarshaller;
 import javax.xml.stream.XMLInputFactory;
 import javax.xml.stream.XMLStreamReader;
 
-public class SiftsClient extends StructureMappingClient implements
-        SiftsClientI
+import MCview.Atom;
+import MCview.PDBChain;
+
+public class SiftsClient implements SiftsClientI
 {
   /*
    * for use in mocking out file fetch for tests only
@@ -79,8 +83,14 @@ public class SiftsClient extends StructureMappingClient implements
    */
   private static File mockSiftsFile;
 
+  private static final int UNASSIGNED = StructureMapping.UNASSIGNED; // -1
+
+  private static final int PDB_RES_POS = StructureMapping.PDB_RES_NUM_INDEX; // 0
+
   private Entry siftsEntry;
 
+  private StructureFile structureFile;
+
   private String pdbId;
 
   private String structId;
@@ -89,9 +99,7 @@ public class SiftsClient extends StructureMappingClient implements
 
   private static final int BUFFER_SIZE = 4096;
 
-  public static final int UNASSIGNED = -1;
-
-  private static final int PDB_RES_POS = 0;
+  private static final int PDB_ATOM_POS = 1;
 
   private static final String NOT_OBSERVED = "Not_Observed";
 
@@ -402,9 +410,8 @@ public class SiftsClient extends StructureMappingClient implements
   }
 
   @Override
-  public StructureMapping getStructureMapping(SequenceI seq,
-          String pdbFile, String chain) throws Exception,
-          StructureMappingException
+  public StructureMapping getSiftsStructureMapping(SequenceI seq,
+          String pdbFile, String chain) throws SiftsException
   {
     structId = (chain == null) ? pdbId : pdbId + "|" + chain;
     System.out.println("Getting SIFTS mapping for " + structId + ": seq "
@@ -435,8 +442,7 @@ public class SiftsClient extends StructureMappingClient implements
 
   @Override
   public HashMap<Integer, int[]> getGreedyMapping(String entityId,
-          SequenceI seq, java.io.PrintStream os) throws SiftsException,
-          StructureMappingException
+          SequenceI seq, java.io.PrintStream os) throws SiftsException
   {
     List<Integer> omitNonObserved = new ArrayList<Integer>();
     int nonObservedShiftIndex = 0;
@@ -572,18 +578,8 @@ public class SiftsClient extends StructureMappingClient implements
                   .equalsIgnoreCase(seqCoordSys.getName())
                   && isAccessionMatched(cRefDb.getDbAccessionId()))
           {
-            String resNumIndexString = cRefDb.getDbResNum()
-                    .equalsIgnoreCase("None") ? String.valueOf(UNASSIGNED)
-                    : cRefDb.getDbResNum();
-            try
-            {
-              currSeqIndex = Integer.valueOf(resNumIndexString);
-            } catch (NumberFormatException nfe)
-            {
-              currSeqIndex = Integer.valueOf(resNumIndexString
-                      .split("[a-zA-Z]")[0]);
-              continue;
-            }
+            currSeqIndex = getLeadingIntegerValue(
+                    cRefDb.getDbResNum(), UNASSIGNED);
             if (pdbRefDb != null)
             {
               break;// exit loop if pdb and uniprot are already found
@@ -596,23 +592,11 @@ public class SiftsClient extends StructureMappingClient implements
         }
         if (currSeqIndex >= seq.getStart() && currSeqIndex <= seq.getEnd())
         {
-          int resNum;
-          try
-          {
-            resNum = (pdbRefDb == null) ? Integer.valueOf(residue
-                    .getDbResNum()) : Integer.valueOf(pdbRefDb
-                    .getDbResNum());
-          } catch (NumberFormatException nfe)
-          {
-            if (pdbRefDb == null || pdbRefDb.getDbResNum().equals("null"))
-            {
-              resNum = UNASSIGNED;
-              continue;
-            }
-            resNum = Integer.valueOf(pdbRefDb
-                    .getDbResNum().split("[a-zA-Z]")[0]);
-            continue;
-          }
+
+          int resNum = (pdbRefDb == null) ? getLeadingIntegerValue(
+                  residue.getDbResNum(), UNASSIGNED)
+                  : getLeadingIntegerValue(pdbRefDb.getDbResNum(),
+                          UNASSIGNED);
 
           if (isResidueObserved(residue)
                   || seqCoordSys == CoordinateSys.UNIPROT)
@@ -634,6 +618,92 @@ public class SiftsClient extends StructureMappingClient implements
     }
   }
 
+  /**
+   * Get the leading integer part of a string that begins with an integer.
+   * 
+   * @param input
+   *          - the string input to process
+   * @param failValue
+   *          - value returned if unsuccessful
+   * @return
+   */
+  static int getLeadingIntegerValue(String input, int failValue)
+  {
+    if (input == null)
+    {
+      return failValue;
+    }
+    String[] parts = input.split("(?=\\D)(?<=\\d)");
+    if (parts != null && parts.length > 0 && parts[0].matches("[0-9]+"))
+    {
+      return Integer.valueOf(parts[0]);
+    }
+    return failValue;
+  }
+
+
+  /**
+   * 
+   * @param chainId
+   *          Target chain to populate mapping of its atom positions.
+   * @param mapping
+   *          Two dimension array of residue index versus atom position
+   * @throws IllegalArgumentException
+   *           Thrown if chainId or mapping is null
+   * @throws SiftsException
+   */
+  void populateAtomPositions(String chainId, Map<Integer, int[]> mapping)
+          throws IllegalArgumentException, SiftsException
+  {
+    try
+    {
+      PDBChain chain = structureFile.findChain(chainId);
+
+      if (chain == null || mapping == null)
+      {
+        throw new IllegalArgumentException(
+                "Chain id or mapping must not be null.");
+      }
+      for (int[] map : mapping.values())
+      {
+        if (map[PDB_RES_POS] != UNASSIGNED)
+        {
+          map[PDB_ATOM_POS] = getAtomIndex(map[PDB_RES_POS], chain.atoms);
+        }
+      }
+    } catch (NullPointerException e)
+    {
+      throw new SiftsException(e.getMessage());
+    } catch (Exception e)
+    {
+      throw new SiftsException(e.getMessage());
+    }
+  }
+
+  /**
+   * 
+   * @param residueIndex
+   *          The residue index used for the search
+   * @param atoms
+   *          A collection of Atom to search
+   * @return atom position for the given residue index
+   */
+  int getAtomIndex(int residueIndex, Collection<Atom> atoms)
+  {
+    if (atoms == null)
+    {
+      throw new IllegalArgumentException(
+              "atoms collection must not be null!");
+    }
+    for (Atom atom : atoms)
+    {
+      if (atom.resNumber == residueIndex)
+      {
+        return atom.atomIndex;
+      }
+    }
+    return UNASSIGNED;
+  }
 
   /**
    * Checks if the residue instance is marked 'Not_observed' or not
@@ -896,8 +966,8 @@ public class SiftsClient extends StructureMappingClient implements
   }
 
   @Override
-  public StringBuffer getMappingOutput(MappingOutputModel mp)
-          throws StructureMappingException
+  public StringBuilder getMappingOutput(MappingOutputModel mp)
+          throws SiftsException
   {
     String seqRes = mp.getSeqResidue();
     String seqName = mp.getSeqName();
@@ -918,7 +988,7 @@ public class SiftsClient extends StructureMappingClient implements
     int nochunks = ((seqRes.length()) / len)
             + ((seqRes.length()) % len > 0 ? 1 : 0);
     // output mappings
-    StringBuffer output = new StringBuffer();
+    StringBuilder output = new StringBuilder(512);
     output.append(NEWLINE);
     output.append("Sequence \u27f7 Structure mapping details").append(
             NEWLINE);
@@ -939,6 +1009,7 @@ public class SiftsClient extends StructureMappingClient implements
     output.append(String.valueOf(pdbEnd));
     output.append(NEWLINE).append(NEWLINE);
 
+    ScoreMatrix pam250 = ScoreModels.getInstance().getPam250();
     int matchedSeqCount = 0;
     for (int j = 0; j < nochunks; j++)
     {
@@ -957,27 +1028,29 @@ public class SiftsClient extends StructureMappingClient implements
       output.append(NEWLINE);
       output.append(new Format("%" + (maxid) + "s").form(" ")).append(" ");
 
-      // Print out the matching chars
+      /*
+       * Print out the match symbols:
+       * | for exact match (ignoring case)
+       * . if PAM250 score is positive
+       * else a space
+       */
       for (int i = 0; i < len; i++)
       {
         try
         {
           if ((i + (j * len)) < seqRes.length())
           {
-            boolean sameChar = Comparison.isSameResidue(
-                    seqRes.charAt(i + (j * len)),
-                    strRes.charAt(i + (j * len)), false);
-            if (sameChar
-                    && !jalview.util.Comparison.isGap(seqRes.charAt(i
-                            + (j * len))))
+            char c1 = seqRes.charAt(i + (j * len));
+            char c2 = strRes.charAt(i + (j * len));
+            boolean sameChar = Comparison.isSameResidue(c1, c2, false);
+            if (sameChar && !Comparison.isGap(c1))
             {
               matchedSeqCount++;
               output.append("|");
             }
             else if (type.equals("pep"))
             {
-              if (ResidueProperties.getPAM250(seqRes.charAt(i + (j * len)),
-                      strRes.charAt(i + (j * len))) > 0)
+              if (pam250.getPairwiseScore(c1, c2) > 0)
               {
                 output.append(".");
               }
@@ -1012,8 +1085,7 @@ public class SiftsClient extends StructureMappingClient implements
     float pid = (float) matchedSeqCount / seqRes.length() * 100;
     if (pid < SiftsSettings.getFailSafePIDThreshold())
     {
-      throw new StructureMappingException(
-              ">>> Low PID detected for SIFTs mapping...");
+      throw new SiftsException(">>> Low PID detected for SIFTs mapping...");
     }
     output.append("Length of alignment = " + seqRes.length()).append(
             NEWLINE);
@@ -1056,4 +1128,5 @@ public class SiftsClient extends StructureMappingClient implements
     mockSiftsFile = file;
   }
 
+
 }