Merge branch 'features/JAL-2944_openStructuresInSelectedView' of https://source.jalvi...
[jalview.git] / src / jalview / structure / StructureSelectionManager.java
index 2b429d7..ad259fd 100644 (file)
@@ -74,8 +74,6 @@ public class StructureSelectionManager
 
   private boolean addTempFacAnnot = false;
 
-  private SiftsClient siftsClient = null;
-
   /*
    * Set of any registered mappings between (dataset) sequences.
    */
@@ -287,7 +285,8 @@ public class StructureSelectionManager
   }
 
   /**
-   * Returns the file name for a mapped PDB id (or null if not mapped).
+   * Returns the filename the PDB id is already mapped to if known, or null if
+   * it is not mapped
    * 
    * @param pdbid
    * @return
@@ -296,7 +295,7 @@ public class StructureSelectionManager
   {
     for (StructureMapping sm : mappings)
     {
-      if (sm.getPdbId().equals(pdbid))
+      if (sm.getPdbId().equalsIgnoreCase(pdbid))
       {
         return sm.pdbfile;
       }
@@ -328,22 +327,20 @@ public class StructureSelectionManager
   }
 
   /**
-   * create sequence structure mappings between each sequence and the given
-   * pdbFile (retrieved via the given protocol).
+   * Import a single structure file and register sequence structure mappings for
+   * broadcasting colouring, mouseovers and selection events (convenience
+   * wrapper).
    * 
    * @param forStructureView
    *          when true, record the mapping for use in mouseOvers
-   * 
-   * @param sequenceArray
+   * @param sequence
    *          - one or more sequences to be mapped to pdbFile
-   * @param targetChainIds
+   * @param targetChains
    *          - optional chain specification for mapping each sequence to pdb
-   *          (may be nill, individual elements may be nill) - JBPNote: JAL-2693
-   *          - this should be List<List<String>>, empty lists indicate no
-   *          predefined mappings
+   *          (may be nill, individual elements may be nill)
    * @param pdbFile
    *          - structure data resource
-   * @param sourceType
+   * @param protocol
    *          - how to resolve data from resource
    * @return null or the structure data parsed as a pdb file
    */
@@ -355,46 +352,51 @@ public class StructureSelectionManager
             pdbFile, sourceType, null);
   }
 
+  /**
+   * create sequence structure mappings between each sequence and the given
+   * pdbFile (retrieved via the given protocol). Either constructs a mapping
+   * using NW alignment or derives one from any available SIFTS mapping data.
+   * 
+   * @param forStructureView
+   *          when true, record the mapping for use in mouseOvers
+   * 
+   * @param sequenceArray
+   *          - one or more sequences to be mapped to pdbFile
+   * @param targetChainIds
+   *          - optional chain specification for mapping each sequence to pdb
+   *          (may be nill, individual elements may be nill) - JBPNote: JAL-2693
+   *          - this should be List<List<String>>, empty lists indicate no
+   *          predefined mappings
+   * @param pdbFile
+   *          - structure data resource
+   * @param sourceType
+   *          - how to resolve data from resource
+   * @param IProgressIndicator
+   *          reference to UI component that maintains a progress bar for the
+   *          mapping operation
+   * @return null or the structure data parsed as a pdb file
+   */
   synchronized public StructureFile computeMapping(
           boolean forStructureView, SequenceI[] sequenceArray,
           String[] targetChainIds, String pdbFile, DataSourceType sourceType,
           IProgressIndicator progress)
   {
     long progressSessionId = System.currentTimeMillis() * 3;
-    /*
-     * There will be better ways of doing this in the future, for now we'll use
-     * the tried and tested MCview pdb mapping
+
+    /**
+     * do we extract and transfer annotation from 3D data ?
      */
-    boolean parseSecStr = processSecondaryStructure;
-    if (isPDBFileRegistered(pdbFile))
-    {
-      for (SequenceI sq : sequenceArray)
-      {
-        SequenceI ds = sq;
-        while (ds.getDatasetSequence() != null)
-        {
-          ds = ds.getDatasetSequence();
-        }
-        ;
-        if (ds.getAnnotation() != null)
-        {
-          for (AlignmentAnnotation ala : ds.getAnnotation())
-          {
-            // false if any annotation present from this structure
-            // JBPNote this fails for jmol/chimera view because the *file* is
-            // passed, not the structure data ID -
-            if (PDBfile.isCalcIdForFile(ala, findIdForPDBFile(pdbFile)))
-            {
-              parseSecStr = false;
-            }
-          }
-        }
-      }
-    }
+    // FIXME: possibly should just delete
+
+    boolean parseSecStr = processSecondaryStructure
+            ? isStructureFileProcessed(pdbFile, sequenceArray)
+            : false;
+
     StructureFile pdb = null;
     boolean isMapUsingSIFTs = SiftsSettings.isMapWithSifts();
     try
     {
+      // FIXME if sourceType is not null, we've lost data here
       sourceType = AppletFormatAdapter.checkProtocol(pdbFile);
       pdb = new JmolParser(pdbFile, sourceType);
 
@@ -411,7 +413,10 @@ public class StructureSelectionManager
       ex.printStackTrace();
       return null;
     }
-
+    /*
+     * sifts client - non null if SIFTS mappings are to be used 
+     */
+    SiftsClient siftsClient = null;
     try
     {
       if (isMapUsingSIFTs)
@@ -422,6 +427,7 @@ public class StructureSelectionManager
     {
       isMapUsingSIFTs = false;
       e.printStackTrace();
+      siftsClient = null;
     }
 
     String targetChainId;
@@ -524,7 +530,7 @@ public class StructureSelectionManager
           try
           {
             siftsMapping = getStructureMapping(seq, pdbFile, targetChainId,
-                    pdb, maxChain, sqmpping, maxAlignseq);
+                    pdb, maxChain, sqmpping, maxAlignseq, siftsClient);
             seqToStrucMapping.add(siftsMapping);
             maxChain.makeExactMapping(siftsMapping, seq);
             maxChain.transferRESNUMFeatures(seq, "IEA: SIFTS");// FIXME: is this
@@ -556,7 +562,8 @@ public class StructureSelectionManager
             try
             {
               siftsMapping = getStructureMapping(seq,
-                      pdbFile, chain.id, pdb, chain, sqmpping, maxAlignseq);
+                      pdbFile, chain.id, pdb, chain, sqmpping, maxAlignseq,
+                      siftsClient);
               foundSiftsMappings.add(siftsMapping);
               chain.makeExactMapping(siftsMapping, seq);
               chain.transferRESNUMFeatures(seq, "IEA: SIFTS");// FIXME: is this
@@ -566,6 +573,13 @@ public class StructureSelectionManager
             {
               System.err.println(e.getMessage());
             }
+            catch (Exception e)
+            {
+              System.err
+                      .println(
+                              "Unexpected exception during SIFTS mapping - falling back to NW for this sequence/structure pair");
+              System.err.println(e.getMessage());
+            }
           }
           if (!foundSiftsMappings.isEmpty())
           {
@@ -599,7 +613,10 @@ public class StructureSelectionManager
       }
       if (forStructureView)
       {
-        mappings.addAll(seqToStrucMapping);
+        for (StructureMapping sm : seqToStrucMapping)
+        {
+          addStructureMapping(sm); // not addAll!
+        }
       }
       if (progress != null)
       {
@@ -609,9 +626,52 @@ public class StructureSelectionManager
     return pdb;
   }
 
+  /**
+   * check if we need to extract secondary structure from given pdbFile and
+   * transfer to sequences
+   * 
+   * @param pdbFile
+   * @param sequenceArray
+   * @return
+   */
+  private boolean isStructureFileProcessed(String pdbFile,
+          SequenceI[] sequenceArray)
+  {
+    boolean parseSecStr = true;
+    if (isPDBFileRegistered(pdbFile))
+    {
+      for (SequenceI sq : sequenceArray)
+      {
+        SequenceI ds = sq;
+        while (ds.getDatasetSequence() != null)
+        {
+          ds = ds.getDatasetSequence();
+        }
+        ;
+        if (ds.getAnnotation() != null)
+        {
+          for (AlignmentAnnotation ala : ds.getAnnotation())
+          {
+            // false if any annotation present from this structure
+            // JBPNote this fails for jmol/chimera view because the *file* is
+            // passed, not the structure data ID -
+            if (PDBfile.isCalcIdForFile(ala, findIdForPDBFile(pdbFile)))
+            {
+              parseSecStr = false;
+            }
+          }
+        }
+      }
+    }
+    return parseSecStr;
+  }
+
   public void addStructureMapping(StructureMapping sm)
   {
-    mappings.add(sm);
+    if (!mappings.contains(sm))
+    {
+      mappings.add(sm);
+    }
   }
 
   /**
@@ -625,13 +685,15 @@ public class StructureSelectionManager
    * @param maxChain
    * @param sqmpping
    * @param maxAlignseq
+   * @param siftsClient
+   *          client for retrieval of SIFTS mappings for this structure
    * @return
    * @throws SiftsException
    */
   private StructureMapping getStructureMapping(SequenceI seq,
           String pdbFile, String targetChainId, StructureFile pdb,
           PDBChain maxChain, jalview.datamodel.Mapping sqmpping,
-          AlignSeq maxAlignseq) throws SiftsException
+          AlignSeq maxAlignseq, SiftsClient siftsClient) throws SiftsException
   {
     StructureMapping curChainMapping = siftsClient
             .getSiftsStructureMapping(seq, pdbFile, targetChainId);