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