JAL-1925 update source version in license
[jalview.git] / src / jalview / analysis / scoremodels / FeatureScoreModel.java
index b946bba..f547dc8 100644 (file)
@@ -1,17 +1,37 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer (Version 2.9.0b2)
+ * Copyright (C) 2015 The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.analysis.scoremodels;
 
-import java.awt.Color;
-import java.util.List;
-
-import jalview.analysis.AlignSeq;
 import jalview.api.analysis.ScoreModelI;
 import jalview.api.analysis.ViewBasedAnalysisI;
 import jalview.datamodel.AlignmentView;
-import jalview.datamodel.SeqCigar;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
 import jalview.util.Comparison;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Hashtable;
+import java.util.List;
+
 public class FeatureScoreModel implements ScoreModelI, ViewBasedAnalysisI
 {
   jalview.api.FeatureRenderer fr;
@@ -27,51 +47,96 @@ public class FeatureScoreModel implements ScoreModelI, ViewBasedAnalysisI
   @Override
   public float[][] findDistances(AlignmentView seqData)
   {
+    int nofeats = 0;
+    List<String> dft = Arrays.asList(fr.getDisplayedFeatureTypes());
+
+    if (dft != null)
+    {
+      nofeats = dft.size();
+    }
 
     SequenceI[] sequenceString = seqData.getVisibleAlignment(
             Comparison.GapChars.charAt(0)).getSequencesArray();
     int noseqs = sequenceString.length;
     int cpwidth = seqData.getWidth();
     float[][] distance = new float[noseqs][noseqs];
+    if (nofeats == 0)
+    {
+      for (float[] d : distance)
+      {
+        for (int i = 0; i < d.length; d[i++] = 0f)
+        {
+          ;
+        }
+      }
+      return distance;
+    }
     float max = 0;
     for (int cpos = 0; cpos < cpwidth; cpos++)
     {
       // get visible features at cpos under view's display settings and compare
       // them
+      List<Hashtable<String, SequenceFeature>> sfap = new ArrayList<Hashtable<String, SequenceFeature>>();
+      for (int i = 0; i < noseqs; i++)
+      {
+        Hashtable<String, SequenceFeature> types = new Hashtable<String, SequenceFeature>();
+        List<SequenceFeature> sfs = fr.findFeaturesAtRes(sequenceString[i],
+                sequenceString[i].findPosition(cpos));
+        for (SequenceFeature sf : sfs)
+        {
+          types.put(sf.getType(), sf);
+        }
+        sfap.add(types);
+      }
       for (int i = 0; i < (noseqs - 1); i++)
       {
-        List<SequenceFeature> sf = fr.findFeaturesAtRes(sequenceString[i],
-                cpos);
+        if (cpos == 0)
+        {
+          distance[i][i] = 0f;
+        }
         for (int j = i + 1; j < noseqs; j++)
         {
-          List<SequenceFeature> jsf = fr.findFeaturesAtRes(
-                  sequenceString[i], cpos);
+          int sfcommon = 0;
           // compare the two lists of features...
-
-          if (max < distance[i][j])
+          Hashtable<String, SequenceFeature> fi = sfap.get(i), fk, fj = sfap
+                  .get(j);
+          if (fi.size() > fj.size())
           {
-            max = distance[i][j];
+            fk = fj;
           }
+          else
+          {
+            fk = fi;
+            fi = fj;
+          }
+          for (String k : fi.keySet())
+          {
+            SequenceFeature sfj = fk.get(k);
+            if (sfj != null)
+            {
+              sfcommon++;
+            }
+          }
+          distance[i][j] += (fi.size() + fk.size() - 2f * sfcommon);
+          distance[j][i] += distance[i][j];
         }
       }
     }
-
-    for (int i = 0; i < (noseqs - 1); i++)
+    for (int i = 0; i < noseqs; i++)
     {
-      for (int j = i; j < noseqs; j++)
+      for (int j = i + 1; j < noseqs; j++)
       {
-        distance[i][j] = max - distance[i][j];
+        distance[i][j] /= cpwidth;
         distance[j][i] = distance[i][j];
       }
     }
-
     return distance;
   }
 
   @Override
   public String getName()
   {
-    return "Smith Waterman Score";
+    return "Sequence Feature Similarity";
   }
 
   @Override
@@ -88,6 +153,6 @@ public class FeatureScoreModel implements ScoreModelI, ViewBasedAnalysisI
 
   public String toString()
   {
-    return "Score between two sequences aligned with Smith Waterman with default Peptide/Nucleotide matrix";
+    return "Score between sequences based on hamming distance between binary vectors marking features displayed at each column";
   }
 }