Merge branch 'develop' into features/JAL-4366_foldseek_3di_viewing
authorJim Procter <jprocter@dundee.ac.uk>
Tue, 3 Sep 2024 13:38:20 +0000 (14:38 +0100)
committerJim Procter <jprocter@dundee.ac.uk>
Tue, 3 Sep 2024 13:50:10 +0000 (14:50 +0100)
 Conflicts:
src/jalview/analysis/AlignSeq.java
src/jalview/analysis/scoremodels/ScoreModels.java
src/jalview/api/AlignViewportI.java
src/jalview/gui/CalculationChooser.java
src/jalview/gui/PairwiseAlignPanel.java
test/jalview/gui/CalculationChooserTest.java

13 files changed:
1  2 
src/jalview/analysis/AlignSeq.java
src/jalview/analysis/AlignmentUtils.java
src/jalview/analysis/scoremodels/ScoreModels.java
src/jalview/api/AlignViewportI.java
src/jalview/bin/Cache.java
src/jalview/gui/AlignViewport.java
src/jalview/gui/CalculationChooser.java
src/jalview/gui/PairwiseAlignPanel.java
src/jalview/structure/StructureSelectionManager.java
src/jalview/viewmodel/AlignmentViewport.java
test/jalview/analysis/AlignmentUtilsTests.java
test/jalview/analysis/scoremodels/ScoreModelsTest.java
test/jalview/gui/CalculationChooserTest.java

@@@ -287,8 -334,10 +334,9 @@@ public class AlignSe
              s2.getDatasetSequence() == null ? s2 : s2.getDatasetSequence());
      return alSeq2;
    }
 -
    /**
     * fraction of seq2 matched in the alignment
+    * 
     * @return NaN or [0..1]
     */
    public double getS2Coverage()
          match++;
        }
      }
+     /*
+      * we built the character strings backwards, so now
+      * reverse them to convert to sequence strings
+      */
+     astr1 = sb1.reverse().toString();
+     astr2 = sb2.reverse().toString();
+   }
+   /**
+    * DOCUMENT ME!
+    */
+   public void traceAlignmentWithEndGaps()
+   {
+     // Find the maximum score along the rhs or bottom row
+     float max = -Float.MAX_VALUE;
+     for (int i = 0; i < seq1.length; i++)
+     {
+       if (score[i][seq2.length - 1] > max)
+       {
+         max = score[i][seq2.length - 1];
+         maxi = i;
+         maxj = seq2.length - 1;
+       }
+     }
+     for (int j = 0; j < seq2.length; j++)
+     {
+       if (score[seq1.length - 1][j] > max)
+       {
+         max = score[seq1.length - 1][j];
+         maxi = seq1.length - 1;
+         maxj = j;
+       }
+     }
+     int i = maxi;
+     int j = maxj;
+     int trace;
+     maxscore = score[i][j] / 10f;
+     // prepare trailing gaps
+     while ((i < seq1.length - 1) || (j < seq2.length - 1))
+     {
+       i++;
+       j++;
+     }
+     seq1end = i + 1;
+     seq2end = j + 1;
+     aseq1 = new int[seq1.length + seq2.length];
+     aseq2 = new int[seq1.length + seq2.length];
+     StringBuilder sb1 = new StringBuilder(aseq1.length);
+     StringBuilder sb2 = new StringBuilder(aseq2.length);
+     count = (seq1.length + seq2.length) - 1;
+     // get trailing gaps
+     while ((i >= seq1.length) || (j >= seq2.length))
+     {
+       if (i >= seq1.length)
+       {
+         aseq1[count] = GAP_INDEX;
+         sb1.append("-");
+         aseq2[count] = seq2[j];
+         sb2.append(s2str.charAt(j));
+       }
+       else if (j >= seq2.length)
+       {
+         aseq1[count] = seq1[i];
+         sb1.append(s1str.charAt(i));
+         aseq2[count] = GAP_INDEX;
+         sb2.append("-");
+       }
+       i--;
+       j--;
+     }
+     while (i > 0 && j > 0)
+     {
+       aseq1[count] = seq1[i];
+       sb1.append(s1str.charAt(i));
+       aseq2[count] = seq2[j];
+       sb2.append(s2str.charAt(j));
+       trace = findTrace(i, j);
+       if (trace == 0)
+       {
+         i--;
+         j--;
+       }
+       else if (trace == 1)
+       {
+         j--;
+         aseq1[count] = GAP_INDEX;
+         sb1.replace(sb1.length() - 1, sb1.length(), "-");
+       }
+       else if (trace == -1)
+       {
+         i--;
+         aseq2[count] = GAP_INDEX;
+         sb2.replace(sb2.length() - 1, sb2.length(), "-");
+       }
+       count--;
+     }
+     seq1start = i + 1;
+     seq2start = j + 1;
+     aseq1[count] = seq1[i];
+     sb1.append(s1str.charAt(i));
+     aseq2[count] = seq2[j];
+     sb2.append(s2str.charAt(j));
+     // get initial gaps
+     while (j > 0 || i > 0)
+     {
+       if (j > 0)
+       {
+         j--;
+         sb1.append("-");
+         sb2.append(s2str.charAt(j));
+       }
+       else if (i > 0)
+       {
+         i--;
+         sb1.append(s1str.charAt(i));
+         sb2.append("-");
+       }
+     }
 -
      /*
       * we built the character strings backwards, so now
       * reverse them to convert to sequence strings
@@@ -41,8 -41,8 +41,10 @@@ public class ScoreModel
  
    private final ScoreMatrix DNA;
  
 +  private final ScoreMatrix FOLDSEEK3DI;
 +
+   private final ScoreMatrix SECONDARYSTRUCTURE;
    private static ScoreModels instance;
  
    private Map<String, ScoreModelI> models;
@@@ -70,7 -70,8 +72,9 @@@
     * <li>PAM250</li>
     * <li>PID</li>
     * <li>DNA</li>
-    * <li>Sequence Feature Similarity</li>
+    * <li>Sequence Feature Similarity</li> *
+    * <li>Secondary Structure Similarity</li>
++   * <li>FOLDSEEK_3di</li>
     * </ul>
     */
    private ScoreModels()
      BLOSUM62 = loadScoreMatrix("scoreModel/blosum62.scm");
      PAM250 = loadScoreMatrix("scoreModel/pam250.scm");
      DNA = loadScoreMatrix("scoreModel/dna.scm");
 +    FOLDSEEK3DI = loadScoreMatrix("scoreModel/foldseek_mat3di.scm");
      registerScoreModel(new PIDModel());
      registerScoreModel(new FeatureDistanceModel());
+     SECONDARYSTRUCTURE = loadScoreMatrix(
+             "scoreModel/secondarystructure.scm");
++    // JBPNote - this overwrites previous
+     registerScoreModel(new SecondaryStructureDistanceModel());
    }
  
    /**
    {
      return PAM250;
    }
+   public ScoreMatrix getSecondaryStructureMatrix()
+   {
+     return SECONDARYSTRUCTURE;
+   }
++
 +  public ScoreMatrix getFOLDSEEK3DI()
 +  {
 +    return FOLDSEEK3DI;
 +  }
-   
  }
@@@ -566,9 -574,20 +574,22 @@@ public interface AlignViewportI extend
     */
    Iterator<int[]> getViewAsVisibleContigs(boolean selectedRegionOnly);
  
+   /**
+    * notify all concerned that the alignment data has changed and derived data
+    * needs to be recalculated
+    */
+   public void notifyAlignmentChanged();
+   /**
+    * retrieve a matrix associated with the view's alignment's annotation
+    * 
+    * @param alignmentAnnotation
+    * @return contact matrix or NULL
+    */
    ContactMatrixI getContactMatrix(AlignmentAnnotation alignmentAnnotation);
 -
+   ProfilesI getSequenceSSConsensusHash();
  
 +  boolean is3di();
 +
 +  public AlignmentAnnotation getComparisonAnnotation();
  }
Simple merge
Simple merge
@@@ -528,8 -700,21 +701,21 @@@ public class CalculationChooser extend
    protected void calculate_actionPerformed()
    {
      boolean doPCA = pca.isSelected();
-     String modelName = modelNames.getSelectedItem().toString();
+     boolean doPaSiMap = pasimap.isSelected();
+     boolean doPairwise = pairwise.isSelected();
+     String modelName = modelNames.getSelectedItem() == null ? ""
+             : modelNames.getSelectedItem().toString();
+     String ssSource = "";
+     Object selectedItem = ssSourceDropdown.getSelectedItem();
+     if (selectedItem != null)
+     {
+       ssSource = selectedItem.toString();
+     }
 -    SimilarityParams params = getSimilarityParameters(doPCA);
 +    SimilarityParamsI params = getSimilarityParameters(doPCA);
+     if (ssSource.length() > 0)
+     {
+       params.setSecondaryStructureSource(ssSource);
+     }
  
      if (doPCA)
      {
@@@ -113,14 -231,19 +233,22 @@@ public class PairwiseAlignPanel extend
          {
            continue;
          }
-         if (params!=null)
 -
++        if (sm!=null)
 +        {
-           as.setScoreMatrix(params);
++          as.setScoreMatrix(sm);
 +        }
          as.calcScoreMatrix();
-         as.traceAlignment();
+         if (endGaps)
+         {
+           as.traceAlignmentWithEndGaps();
+         }
+         else
+         {
+           as.traceAlignment();
+         }
+         as.scoreAlignment();
  
-         if (!first)
+         if (!first && !quiet)
          {
            jalview.bin.Console.outPrintln(DASHES);
            textarea.append(DASHES);
@@@ -75,9 -75,9 +76,10 @@@ import jalview.util.MappingUtils
  import jalview.util.MessageManager;
  import jalview.viewmodel.styles.ViewStyle;
  import jalview.workers.AlignCalcManager;
 +import jalview.workers.AlignmentComparisonThread;
  import jalview.workers.ComplementConsensusThread;
  import jalview.workers.ConsensusThread;
+ import jalview.workers.SecondaryStructureConsensusThread;
  import jalview.workers.StrucConsensusThread;
  
  /**
@@@ -897,20 -921,26 +923,38 @@@ public abstract class AlignmentViewpor
          }
        }
      }
 +    if (getCodingComplement() != null)
 +    {
 +      if (getCodingComplement().isNucleotide() == isNucleotide())
 +      {
 +        if (calculator.getRegisteredWorkersOfClass(
 +                AlignmentComparisonThread.class) == null)
 +        {
 +          initAlignmentComparison(ap);
 +          ap.adjustAnnotationHeight();
 +        }
 +      }
 +    }
    }
  
+   /**
+    * trigger update of consensus annotation
+    */
+   public void updateSecondaryStructureConsensus(final AlignmentViewPanel ap)
+   {
+     // see note in mantis : issue number 8585
+     if (secondaryStructureConsensus == null || !autoCalculateConsensus)
+     {
+       return;
+     }
+     if (calculator.getRegisteredWorkersOfClass(
+             SecondaryStructureConsensusThread.class) == null)
+     {
+       calculator.registerWorker(
+               new SecondaryStructureConsensusThread(this, ap));
+     }
+   }
    // --------START Structure Conservation
    public void updateStrucConsensus(final AlignmentViewPanel ap)
    {
@@@ -55,24 -55,28 +55,31 @@@ public class CalculationChooserTes
       * peptide models for PCA
       */
      List<ScoreModelI> filtered = CalculationChooser
-             .getApplicableScoreModels(false, true);
-     assertEquals(filtered.size(), 5);
+             .getApplicableScoreModels(false, true, true, false);
 -    assertEquals(filtered.size(), 5);
++    assertEquals(filtered.size(), 6);
      assertSame(filtered.get(0), blosum62);
      assertSame(filtered.get(1), pam250);
 -    assertEquals(filtered.get(2).getName(), "PID");
 -    assertEquals(filtered.get(3).getName(), "Sequence Feature Similarity");
 -    assertEquals(filtered.get(4).getName(),
 +    assertEquals(filtered.get(2).getName(), "Mat3di");
 +    assertEquals(filtered.get(4).getName(), "Sequence Feature Similarity");
++    assertEquals(filtered.get(5).getName(),
+             "Secondary Structure Similarity");
  
      /*
       * peptide models for Tree are the same
       */
-     filtered = CalculationChooser.getApplicableScoreModels(false, false);
-     assertEquals(filtered.size(), 5);
+     filtered = CalculationChooser.getApplicableScoreModels(false, false,
+             true, false);
 -    assertEquals(filtered.size(), 5);
++    assertEquals(filtered.size(), 6);
++
      assertSame(filtered.get(0), blosum62);
      assertSame(filtered.get(1), pam250);
 -    assertEquals(filtered.get(2).getName(), "PID");
 -    assertEquals(filtered.get(3).getName(), "Sequence Feature Similarity");
 +    assertEquals(filtered.get(2).getName(), "Mat3di");
 +    assertEquals(filtered.get(3).getName(), "PID");
 +    assertEquals(filtered.get(4).getName(), "Sequence Feature Similarity");
+     assertEquals(filtered.get(4).getName(),
+             "Secondary Structure Similarity");
 +
      /*
       * nucleotide models for PCA
       */
      /*
       * nucleotide models for Tree are unchanged
       */
-     filtered = CalculationChooser.getApplicableScoreModels(true, false);
+     filtered = CalculationChooser.getApplicableScoreModels(true, false,
+             true, false);
 -    assertEquals(filtered.size(), 4);
 +    assertEquals(filtered.size(), 3);
      assertSame(filtered.get(0), dna);
      assertEquals(filtered.get(1).getName(), "PID");
      assertEquals(filtered.get(2).getName(), "Sequence Feature Similarity");