JAL-1483 patches to make test case pass: hamming distance counts differences in prese...
[jalview.git] / src / jalview / analysis / scoremodels / FeatureScoreModel.java
1 package jalview.analysis.scoremodels;
2
3 import jalview.api.analysis.ScoreModelI;
4 import jalview.api.analysis.ViewBasedAnalysisI;
5 import jalview.datamodel.AlignmentView;
6 import jalview.datamodel.SequenceFeature;
7 import jalview.datamodel.SequenceI;
8 import jalview.util.Comparison;
9
10 import java.util.ArrayList;
11 import java.util.Arrays;
12 import java.util.Hashtable;
13 import java.util.List;
14
15 public class FeatureScoreModel implements ScoreModelI, ViewBasedAnalysisI
16 {
17   jalview.api.FeatureRenderer fr;
18
19   @Override
20   public boolean configureFromAlignmentView(
21           jalview.api.AlignmentViewPanel view)
22   {
23     fr = view.cloneFeatureRenderer();
24     return true;
25   }
26
27   @Override
28   public float[][] findDistances(AlignmentView seqData)
29   {
30     int nofeats = 0;
31     List<String> dft = Arrays.asList(fr.getDisplayedFeatureTypes());
32
33     if (dft != null)
34     {
35       nofeats = dft.size();
36     }
37
38     SequenceI[] sequenceString = seqData.getVisibleAlignment(
39             Comparison.GapChars.charAt(0)).getSequencesArray();
40     int noseqs = sequenceString.length;
41     int cpwidth = seqData.getWidth();
42     float[][] distance = new float[noseqs][noseqs];
43     if (nofeats == 0)
44     {
45       for (float[] d : distance)
46       {
47         for (int i = 0; i < d.length; d[i++] = 0f)
48         {
49           ;
50         }
51       }
52       return distance;
53     }
54     float max = 0;
55     for (int cpos = 0; cpos < cpwidth; cpos++)
56     {
57       // get visible features at cpos under view's display settings and compare
58       // them
59       List<Hashtable<String, SequenceFeature>> sfap = new ArrayList<Hashtable<String, SequenceFeature>>();
60       for (int i = 0; i < noseqs; i++)
61       {
62         Hashtable<String, SequenceFeature> types = new Hashtable<String, SequenceFeature>();
63         List<SequenceFeature> sfs = fr.findFeaturesAtRes(sequenceString[i],
64                 sequenceString[i].findPosition(cpos));
65         for (SequenceFeature sf : sfs)
66         {
67           types.put(sf.getType(), sf);
68         }
69         sfap.add(types);
70       }
71       for (int i = 0; i < (noseqs - 1); i++)
72       {
73         if (cpos == 0)
74         {
75           distance[i][i] = 0f;
76         }
77         for (int j = i + 1; j < noseqs; j++)
78         {
79           int sfcommon = 0;
80           // compare the two lists of features...
81           Hashtable<String, SequenceFeature> fi = sfap.get(i), fk, fj = sfap
82                   .get(j);
83           if (fi.size() > fj.size())
84           {
85             fk = fj;
86           }
87           else
88           {
89             fk = fi;
90             fi = fj;
91           }
92           for (String k : fi.keySet())
93           {
94             SequenceFeature sfj = fk.get(k);
95             if (sfj != null)
96             {
97               sfcommon++;
98             }
99           }
100           distance[i][j] += (fi.size() + fk.size() - 2f * sfcommon);
101           distance[j][i] += distance[i][j];
102         }
103       }
104     }
105     for (int i = 0; i < noseqs; i++)
106     {
107       for (int j = i + 1; j < noseqs; j++)
108       {
109         distance[i][j] /= cpwidth;
110         distance[j][i] = distance[i][j];
111       }
112     }
113     return distance;
114   }
115
116   @Override
117   public String getName()
118   {
119     return "Sequence Feature Similarity";
120   }
121
122   @Override
123   public boolean isDNA()
124   {
125     return true;
126   }
127
128   @Override
129   public boolean isProtein()
130   {
131     return true;
132   }
133
134   public String toString()
135   {
136     return "Score between sequences based on hamming distance between binary vectors marking features displayed at each column";
137   }
138 }