Merge branch 'develop' into features/JAL-518_justify_seqs_in_region
[jalview.git] / src / jalview / structure / StructureSelectionManager.java
index c8a846c..9a9e2a2 100644 (file)
@@ -34,6 +34,7 @@ import java.util.Vector;
 
 import jalview.analysis.AlignSeq;
 import jalview.api.StructureSelectionManagerProvider;
+import jalview.bin.Cache;
 import jalview.bin.Console;
 import jalview.commands.CommandI;
 import jalview.commands.EditCommand;
@@ -42,6 +43,7 @@ import jalview.datamodel.AlignedCodonFrame;
 import jalview.datamodel.AlignmentAnnotation;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.Annotation;
+import jalview.datamodel.ContiguousI;
 import jalview.datamodel.HiddenColumns;
 import jalview.datamodel.PDBEntry;
 import jalview.datamodel.SearchResults;
@@ -49,9 +51,11 @@ import jalview.datamodel.SearchResultsI;
 import jalview.datamodel.SequenceI;
 import jalview.ext.jmol.JmolParser;
 import jalview.gui.IProgressIndicator;
+import jalview.gui.Preferences;
 import jalview.io.AppletFormatAdapter;
 import jalview.io.DataSourceType;
 import jalview.io.StructureFile;
+import jalview.structure.StructureImportSettings.TFType;
 import jalview.util.MappingUtils;
 import jalview.util.MessageManager;
 import jalview.util.Platform;
@@ -153,16 +157,18 @@ public class StructureSelectionManager
   {
     if (mappings.isEmpty())
     {
-      System.err.println("reportMapping: No PDB/Sequence mappings.");
+      jalview.bin.Console
+              .errPrintln("reportMapping: No PDB/Sequence mappings.");
     }
     else
     {
-      System.err.println(
+      jalview.bin.Console.errPrintln(
               "reportMapping: There are " + mappings.size() + " mappings.");
       int i = 0;
       for (StructureMapping sm : mappings)
       {
-        System.err.println("mapping " + i++ + " : " + sm.pdbfile);
+        jalview.bin.Console
+                .errPrintln("mapping " + i++ + " : " + sm.pdbfile);
       }
     }
   }
@@ -325,7 +331,7 @@ public class StructureSelectionManager
           IProgressIndicator progress)
   {
     return computeMapping(true, sequence, targetChains, pdbFile, protocol,
-            progress);
+            progress, null, null, true);
   }
 
   /**
@@ -348,10 +354,50 @@ public class StructureSelectionManager
    */
   synchronized public StructureFile setMapping(boolean forStructureView,
           SequenceI[] sequenceArray, String[] targetChainIds,
-          String pdbFile, DataSourceType sourceType)
+          String pdbFile, DataSourceType sourceType, TFType tft,
+          String paeFilename)
+  {
+    return setMapping(forStructureView, sequenceArray, targetChainIds,
+            pdbFile, sourceType, tft, paeFilename, true);
+  }
+
+  /**
+   * 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 tft
+   *          - specify how to interpret the temperature factor column in the
+   *          atom data
+   * @param paeFilename
+   *          - when not null, specifies a filename containing a matrix
+   *          formatted in JSON using one of the known PAE formats
+   * @param doXferSettings
+   *          - when true, transfer annotation to mapped sequences in
+   *          sequenceArray
+   * @return null or the structure data parsed as a pdb file
+   */
+  synchronized public StructureFile setMapping(boolean forStructureView,
+          SequenceI[] sequenceArray, String[] targetChainIds,
+          String pdbFile, DataSourceType sourceType, TFType tft,
+          String paeFilename, boolean doXferSettings)
   {
     return computeMapping(forStructureView, sequenceArray, targetChainIds,
-            pdbFile, sourceType, null);
+            pdbFile, sourceType, null, tft, paeFilename, doXferSettings);
   }
 
   /**
@@ -376,12 +422,22 @@ public class StructureSelectionManager
    * @param IProgressIndicator
    *          reference to UI component that maintains a progress bar for the
    *          mapping operation
+   * @param tft
+   *          - specify how to interpret the temperature factor column in the
+   *          atom data
+   * @param paeFilename
+   *          - when not null, specifies a filename containing a matrix
+   *          formatted in JSON using one of the known PAE formats
+   * @param doXferSettings
+   *          - when true, transfer annotation to mapped sequences in
+   *          sequenceArray
    * @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)
+          IProgressIndicator progress, TFType tft, String paeFilename,
+          boolean doXferSettings)
   {
     long progressSessionId = System.currentTimeMillis() * 3;
 
@@ -391,8 +447,7 @@ public class StructureSelectionManager
     // FIXME: possibly should just delete
 
     boolean parseSecStr = processSecondaryStructure
-            ? isStructureFileProcessed(pdbFile, sequenceArray)
-            : false;
+            && !isStructureFileProcessed(pdbFile, sequenceArray);
 
     StructureFile pdb = null;
     boolean isMapUsingSIFTs = SiftsSettings.isMapWithSifts();
@@ -401,10 +456,19 @@ public class StructureSelectionManager
       // FIXME if sourceType is not null, we've lost data here
       sourceType = AppletFormatAdapter.checkProtocol(pdbFile);
       pdb = new JmolParser(false, pdbFile, sourceType);
+      if (paeFilename != null)
+      {
+        pdb.setPAEMatrix(paeFilename);
+      }
+      pdb.setTemperatureFactorType(tft);
       pdb.addSettings(parseSecStr && processSecondaryStructure,
               parseSecStr && addTempFacAnnot,
               parseSecStr && secStructServices);
+      // save doXferSettings and reset after doParse()
+      boolean temp = pdb.getDoXferSettings();
+      pdb.setDoXferSettings(doXferSettings);
       pdb.doParse();
+      pdb.setDoXferSettings(temp);
       if (pdb.getId() != null && pdb.getId().trim().length() > 0
               && DataSourceType.FILE == sourceType)
       {
@@ -593,12 +657,12 @@ public class StructureSelectionManager
               chain.transferResidueAnnotation(siftsMapping, null);
             } catch (SiftsException e)
             {
-              System.err.println(e.getMessage());
+              jalview.bin.Console.errPrintln(e.getMessage());
             } catch (Exception e)
             {
-              System.err.println(
+              jalview.bin.Console.errPrintln(
                       "Unexpected exception during SIFTS mapping - falling back to NW for this sequence/structure pair");
-              System.err.println(e.getMessage());
+              jalview.bin.Console.errPrintln(e.getMessage());
             }
           }
           if (!foundSiftsMappings.isEmpty())
@@ -659,7 +723,7 @@ public class StructureSelectionManager
   private boolean isStructureFileProcessed(String pdbFile,
           SequenceI[] sequenceArray)
   {
-    boolean parseSecStr = true;
+    boolean processed = false;
     if (isPDBFileRegistered(pdbFile))
     {
       for (SequenceI sq : sequenceArray)
@@ -679,13 +743,13 @@ public class StructureSelectionManager
             // passed, not the structure data ID -
             if (PDBfile.isCalcIdForFile(ala, findIdForPDBFile(pdbFile)))
             {
-              parseSecStr = false;
+              processed = true;
             }
           }
         }
       }
     }
-    return parseSecStr;
+    return processed;
   }
 
   public void addStructureMapping(StructureMapping sm)
@@ -874,6 +938,52 @@ public class StructureSelectionManager
   }
 
   /**
+   * hack to highlight a range of positions at once on any structure views
+   * 
+   * @param sequenceRef
+   * @param is
+   *          - series of int start-end ranges as positions on sequenceRef
+   * @param i
+   * @param object
+   */
+  public void highlightPositionsOn(SequenceI sequenceRef, int[][] is,
+          Object source)
+  {
+    boolean hasSequenceListeners = handlingVamsasMo
+            || !seqmappings.isEmpty();
+    SearchResultsI results = null;
+    ArrayList<Integer> listOfPositions = new ArrayList<Integer>();
+    for (int[] s_e : is)
+    {
+      for (int p = s_e[0]; p <= s_e[1]; listOfPositions.add(p++))
+        ;
+    }
+    int seqpos[] = new int[listOfPositions.size()];
+    int i = 0;
+    for (Integer p : listOfPositions)
+    {
+      seqpos[i++] = p;
+    }
+
+    for (i = 0; i < listeners.size(); i++)
+    {
+      Object listener = listeners.elementAt(i);
+      if (listener == source)
+      {
+        // TODO listener (e.g. SeqPanel) is never == source (AlignViewport)
+        // Temporary fudge with SequenceListener.getVamsasSource()
+        continue;
+      }
+      if (listener instanceof StructureListener)
+      {
+        highlightStructure((StructureListener) listener, sequenceRef,
+                seqpos);
+      }
+
+    }
+  }
+
+  /**
    * Propagate mouseover of a single position in a structure
    * 
    * @param pdbResNum
@@ -955,7 +1065,7 @@ public class StructureSelectionManager
           int indexpos = sm.getSeqPos(atom.getPdbResNum());
           if (lastipos != indexpos || lastseq != sm.sequence)
           {
-            results.addResult(sm.sequence, indexpos, indexpos);
+            results.appendResult(sm.sequence, indexpos, indexpos);
             lastipos = indexpos;
             lastseq = sm.sequence;
             // construct highlighted sequence list
@@ -1083,6 +1193,62 @@ public class StructureSelectionManager
     sl.highlightAtoms(atoms);
   }
 
+  public void highlightStructureRegionsFor(StructureListener sl,
+          SequenceI[] seqs, int... columns)
+  {
+    List<SequenceI> to_highlight = new ArrayList<SequenceI>();
+    for (SequenceI seq : seqs)
+    {
+      if (sl.isListeningFor(seq))
+      {
+        to_highlight.add(seq);
+      }
+    }
+    if (to_highlight.size() == 0)
+    {
+      return;
+    }
+    List<AtomSpec> atoms = new ArrayList<>();
+    for (SequenceI seq : to_highlight)
+    {
+      int atomNo;
+      for (StructureMapping sm : mappings)
+      {
+        if (sm.sequence == seq || sm.sequence == seq.getDatasetSequence()
+                || (sm.sequence.getDatasetSequence() != null && sm.sequence
+                        .getDatasetSequence() == seq.getDatasetSequence()))
+        {
+
+          for (int i = 0; i < columns.length; i += 2)
+          {
+            ContiguousI positions = seq.findPositions(columns[i] + 1,
+                    columns[i + 1] + 1);
+            if (positions == null)
+            {
+              continue;
+            }
+            for (int index = positions.getBegin(); index <= positions
+                    .getEnd(); index++)
+            {
+
+              atomNo = sm.getAtomNum(index);
+
+              if (atomNo > 0)
+              {
+                atoms.add(new AtomSpec(sm.pdbfile, sm.pdbchain,
+                        sm.getPDBResNum(index), atomNo));
+              }
+            }
+          }
+        }
+      }
+      if (atoms.size() > 0)
+      {
+        sl.highlightAtoms(atoms);
+      }
+    }
+  }
+
   /**
    * true if a mouse over event from an external (ie Vamsas) source is being
    * handled
@@ -1128,7 +1294,7 @@ public class StructureSelectionManager
      * 
      * if (mappings[j].sequence == seq && mappings[j].getPdbId().equals(pdbid)
      * && mappings[j].pdbfile.equals(sl.getPdbFile())) {
-     * System.out.println(pdbid+" "+mappings[j].getPdbId() +"
+     * jalview.bin.Console.outPrintln(pdbid+" "+mappings[j].getPdbId() +"
      * "+mappings[j].pdbfile);
      * 
      * java.awt.Color col; for(int index=0; index<seq.getLength(); index++) {
@@ -1225,7 +1391,7 @@ public class StructureSelectionManager
       boolean removed = seqmappings.remove(acf);
       if (removed && seqmappings.isEmpty())
       { // debug
-        System.out.println("All mappings removed");
+        jalview.bin.Console.outPrintln("All mappings removed");
       }
     }
   }
@@ -1461,4 +1627,74 @@ public class StructureSelectionManager
     return seqmappings;
   }
 
+  /**
+   * quick and dirty route to just highlight all structure positions for a range
+   * of columns
+   * 
+   * @param sequencesArray
+   * @param is
+   *          start-end columns on sequencesArray
+   * @param source
+   *          origin parent AlignmentPanel
+   */
+  public void highlightPositionsOnMany(SequenceI[] sequencesArray, int[] is,
+          Object source)
+  {
+    for (int i = 0; i < listeners.size(); i++)
+    {
+      Object listener = listeners.elementAt(i);
+      if (listener == source)
+      {
+        // TODO listener (e.g. SeqPanel) is never == source (AlignViewport)
+        // Temporary fudge with SequenceListener.getVamsasSource()
+        continue;
+      }
+      if (listener instanceof StructureListener)
+      {
+        highlightStructureRegionsFor((StructureListener) listener,
+                sequencesArray, is);
+      }
+    }
+  }
+
+  public Map<String, String> getPdbFileNameIdMap()
+  {
+    return pdbFileNameId;
+  }
+
+  public Map<String, String> getPdbIdFileNameMap()
+  {
+    return pdbIdFileName;
+  }
+
+  public static void doConfigureStructurePrefs(
+          StructureSelectionManager ssm)
+  {
+    doConfigureStructurePrefs(ssm,
+            Cache.getDefault(Preferences.ADD_SS_ANN, true),
+            Cache.getDefault(Preferences.ADD_TEMPFACT_ANN, true),
+            Cache.getDefault(Preferences.STRUCT_FROM_PDB, true),
+            Cache.getDefault(Preferences.USE_RNAVIEW, false));
+  }
+
+  public static void doConfigureStructurePrefs(
+          StructureSelectionManager ssm, boolean add_ss_ann,
+          boolean add_tempfact_ann, boolean struct_from_pdb,
+          boolean use_rnaview)
+  {
+    if (add_ss_ann)
+    {
+      ssm.setAddTempFacAnnot(add_tempfact_ann);
+      ssm.setProcessSecondaryStructure(struct_from_pdb);
+      // JAL-3915 - RNAView is no longer an option so this has no effect
+      ssm.setSecStructServices(use_rnaview);
+    }
+    else
+    {
+      ssm.setAddTempFacAnnot(false);
+      ssm.setProcessSecondaryStructure(false);
+      ssm.setSecStructServices(false);
+    }
+  }
+
 }