JAL-3855 JAL-2349 download PAE matrix along with alpha fold structure from EBI and...
authorJim Procter <j.procter@dundee.ac.uk>
Wed, 18 Aug 2021 15:41:55 +0000 (16:41 +0100)
committerJim Procter <j.procter@dundee.ac.uk>
Wed, 18 Aug 2021 15:41:55 +0000 (16:41 +0100)
src/jalview/ws/dbsources/EBIAlfaFold.java
test/jalview/ws/seqfetcher/DbRefFetcherTest.java

index 5edcafa..6c7818b 100644 (file)
 package jalview.ws.dbsources;
 
 import jalview.api.FeatureSettingsModelI;
+import jalview.bin.Cache;
 import jalview.datamodel.AlignmentAnnotation;
 import jalview.datamodel.AlignmentI;
+import jalview.datamodel.ContactMatrix;
+import jalview.datamodel.ContactMatrixI;
 import jalview.datamodel.DBRefEntry;
 import jalview.datamodel.DBRefSource;
 import jalview.datamodel.PDBEntry;
@@ -34,15 +37,23 @@ import jalview.io.FileFormat;
 import jalview.io.FileFormatI;
 import jalview.io.FormatAdapter;
 import jalview.io.PDBFeatureSettings;
+import jalview.javascript.json.JSON;
 import jalview.structure.StructureImportSettings;
 import jalview.util.HttpUtils;
 import jalview.util.MessageManager;
+import jalview.util.Platform;
+import jalview.ws.datamodel.alphafold.PAEContactMatrix;
 import jalview.ws.ebi.EBIFetchClient;
 import jalview.ws.utils.UrlDownloadClient;
 
+import java.io.BufferedReader;
 import java.io.File;
+import java.io.FileInputStream;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
+
+import org.jmol.adapter.readers.simple.JSONReader;
 
 import com.stevesoft.pat.Regex;
 
@@ -106,10 +117,18 @@ public class EBIAlfaFold extends EbiFileRetrievedProxy
   {
     return "1";
   }
+
   public static String getAlphaFoldCifDownloadUrl(String id)
   {
-    return "https://alphafold.ebi.ac.uk/files/"+id+"-model_v1.cif";
+    return "https://alphafold.ebi.ac.uk/files/" + id + "-model_v1.cif";
+  }
+
+  public static String getAlphaFoldPaeDownloadUrl(String id)
+  {
+    return "https://alphafold.ebi.ac.uk/files/" + id
+            + "-predicted_aligned_error_v1.json";
   }
+
   /*
    * (non-Javadoc)
    * 
@@ -133,24 +152,27 @@ public class EBIAlfaFold extends EbiFileRetrievedProxy
 
     if (!isValidReference(id))
     {
-      System.err.println("(AFClient) Ignoring invalid pdb query: '" + id + "'");
+      System.err.println(
+              "(AFClient) Ignoring invalid alphafold query: '" + id + "'");
       stopQuery();
       return null;
     }
     String alphaFoldCif = getAlphaFoldCifDownloadUrl(id);
-    
-    try {
-      File tmpFile = File.createTempFile(id,"cif");
+
+    try
+    {
+      File tmpFile = File.createTempFile(id, "cif");
       UrlDownloadClient.download(alphaFoldCif, tmpFile);
       file = tmpFile.getAbsolutePath();
       if (file == null)
       {
-      return null;
-    }
+        return null;
+      }
+
       // todo get rid of Type and use FileFormatI instead?
       FileFormatI fileFormat = FileFormat.MMCif;
-      pdbAlignment = new FormatAdapter().readFile(tmpFile, DataSourceType.FILE,
-              fileFormat);
+      pdbAlignment = new FormatAdapter().readFile(tmpFile,
+              DataSourceType.FILE, fileFormat);
       if (pdbAlignment != null)
       {
         List<SequenceI> toremove = new ArrayList<SequenceI>();
@@ -172,8 +194,7 @@ public class EBIAlfaFold extends EbiFileRetrievedProxy
           {
             // FIXME seems to result in 'PDB|1QIP|1qip|A' - 1QIP is redundant.
             // TODO: suggest simplify naming to 1qip|A as default name defined
-            pdbcs.setName(id
-                    + SEPARATOR + pdbcs.getName());
+            pdbcs.setName(id + SEPARATOR + pdbcs.getName());
             // Might need to add more metadata to the PDBEntry object
             // like below
             /*
@@ -223,6 +244,17 @@ public class EBIAlfaFold extends EbiFileRetrievedProxy
                 { id, ((chain == null) ? "' '" : chain) }));
       }
 
+      // import PAE as contact matrix - assume this will work if there was a
+      // model
+      File pae = File.createTempFile(id, "pae_json");
+      String paeURL = getAlphaFoldPaeDownloadUrl(id);
+      UrlDownloadClient.download(paeURL, pae);
+      if (!importPaeJSONAsContactMatrix(pdbAlignment, pae))
+      {
+        Cache.log.debug("Couln't import contact matrix from " + paeURL
+                + " (stored in " + pae.toString() + ")");
+      }
+
     } catch (Exception ex) // Problem parsing PDB file
     {
       stopQuery();
@@ -231,6 +263,24 @@ public class EBIAlfaFold extends EbiFileRetrievedProxy
     return pdbAlignment;
   }
 
+  private boolean importPaeJSONAsContactMatrix(AlignmentI pdbAlignment,
+          File pae) throws Exception
+  {
+    FileInputStream pae_input = new FileInputStream(pae);
+
+    List<Object> pae_obj = (List<Object>) Platform
+            .parseJSON(pae_input);
+    if (pae_obj == null)
+    {
+      return false;
+    }
+    ContactMatrixI matrix = new PAEContactMatrix(
+            pdbAlignment.getSequenceAt(0), (Map<String, Object>)pae_obj.get(0));
+
+    pdbAlignment.getSequenceAt(0).addAlignmentAnnotation(pdbAlignment.addContactList(matrix));
+    return true;
+  }
+
   /*
    * (non-Javadoc)
    * 
@@ -249,13 +299,13 @@ public class EBIAlfaFold extends EbiFileRetrievedProxy
   @Override
   public String getTestQuery()
   {
-    return "1QIP";
+    return "AF-O15552-F1";
   }
 
   @Override
   public String getDbName()
   {
-    return "PDB"; // getDbSource();
+    return "ALPHAFOLD"; // getDbSource();
   }
 
   @Override
index a7e5806..bf34ea5 100644 (file)
  */
 package jalview.ws.seqfetcher;
 
+import static org.testng.Assert.assertNotEquals;
 import static org.testng.AssertJUnit.assertEquals;
 import static org.testng.AssertJUnit.assertFalse;
 import static org.testng.AssertJUnit.assertNotNull;
 import static org.testng.AssertJUnit.assertTrue;
 
 import jalview.analysis.CrossRef;
+import jalview.datamodel.AlignmentAnnotation;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.DBRefEntry;
 import jalview.datamodel.DBRefSource;
@@ -35,6 +37,7 @@ import jalview.datamodel.SequenceI;
 import jalview.gui.JvOptionPane;
 import jalview.util.DBRefUtils;
 import jalview.ws.SequenceFetcher;
+import jalview.ws.dbsources.EBIAlfaFold;
 import jalview.ws.dbsources.Pdb;
 import jalview.ws.dbsources.Uniprot;
 
@@ -42,6 +45,7 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
+import org.junit.Assert;
 import org.testng.annotations.AfterClass;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
@@ -202,4 +206,29 @@ public class DbRefFetcherTest
     assertEquals(dr.get(0).getSource() + "|" + dr.get(0).getAccessionId(),
             proteinSeq.getName());
   }
+
+  /**
+   * Tests retrieval of one entry from EMBLCDS. Test is dependent on
+   * availability of network and the EMBLCDS service.
+   * 
+   * @throws Exception
+   */
+  @Test(groups = { "External" })
+  public void testAlphaFoldClien() throws Exception
+  {
+    DbSourceProxy alphafold = new EBIAlfaFold();
+    AlignmentI resp = alphafold.getSequenceRecords(alphafold.getTestQuery());
+    assertNotNull(resp);
+    assertEquals("One sequence only",resp.getHeight(), 1);
+    for (AlignmentAnnotation aa:resp.getAlignmentAnnotation()) {
+      if (aa.graph == AlignmentAnnotation.CUSTOMRENDERER)
+      {
+        assertTrue("Contact map didn't provide valid contact",resp.getContactListFor(aa, 1).getContactAt(1)!=-1d);
+        // test passes
+        return;
+      }
+    }
+    Assert.fail();
+  }
+
 }