JAL-535 refactored core code from PCA viewer to viewmodel.
[jalview.git] / src / jalview / viewmodel / PCAModel.java
1 package jalview.viewmodel;
2
3 import java.util.Vector;
4
5 import jalview.analysis.PCA;
6 import jalview.datamodel.AlignmentView;
7 import jalview.datamodel.SequenceI;
8 import jalview.datamodel.SequencePoint;
9 import jalview.api.RotatableCanvasI;
10
11 public class PCAModel
12 {
13
14   public PCAModel(AlignmentView seqstrings2, SequenceI[] seqs2,
15           boolean nucleotide2)
16   {
17     seqstrings=seqstrings2;
18     seqs=seqs2;
19     nucleotide=nucleotide2;
20   }
21
22   PCA pca;
23   
24   int top;
25   
26   AlignmentView seqstrings;
27
28   SequenceI[] seqs;
29
30   /**
31    * use the identity matrix for calculating similarity between sequences. 
32    */
33   private boolean nucleotide=false;
34
35   private Vector<SequencePoint> points;
36
37   public void run()
38   {
39     
40     pca = new PCA(seqstrings.getSequenceStrings(' '), nucleotide);
41     pca.run();
42
43     // Now find the component coordinates
44     int ii = 0;
45
46     while ((ii < seqs.length) && (seqs[ii] != null))
47     {
48       ii++;
49     }
50
51     double[][] comps = new double[ii][ii];
52
53     for (int i = 0; i < ii; i++)
54     {
55       if (pca.getEigenvalue(i) > 1e-4)
56       {
57         comps[i] = pca.component(i);
58       }
59     }
60
61     top = pca.getM().rows - 1;
62
63     points = new Vector<SequencePoint>();
64     float[][] scores = pca.getComponents(top - 1, top - 2, top - 3, 100);
65
66     for (int i = 0; i < pca.getM().rows; i++)
67     {
68       SequencePoint sp = new SequencePoint(seqs[i], scores[i]);
69       points.addElement(sp);
70     }
71     
72   }
73
74   public void updateRc(RotatableCanvasI rc)
75   {
76     rc.setPoints(points, pca.getM().rows);
77   }
78
79   public boolean isNucleotide()
80   {
81     return nucleotide;
82   }
83   public void setNucleotide(boolean nucleotide)
84   {
85     this.nucleotide=nucleotide;
86   }
87
88   /**
89    * 
90    * 
91    * @return index of principle dimension of PCA
92    */
93   public int getTop()
94   {
95     return top;
96   }
97
98   /**
99    * update the 2d coordinates for the list of points to the given dimensions
100    * Principal dimension is getTop(). Next greated eigenvector is getTop()-1.
101    * Note - pca.getComponents starts counting the spectrum from zero rather than one, so getComponents(dimN ...)  == updateRcView(dimN+1 ..)  
102    * @param dim1 
103    * @param dim2
104    * @param dim3
105    */
106   public void updateRcView(int dim1, int dim2, int dim3)
107   {
108     float[][] scores = pca.getComponents(dim1-1, dim2-1, dim3-1, 100);
109
110     for (int i = 0; i < pca.getM().rows; i++)
111     {
112       ((SequencePoint) points.elementAt(i)).coord = scores[i];
113     }
114   }
115
116   public String getDetails()
117   {
118     return pca.getDetails();
119   }
120
121   public AlignmentView getSeqtrings()
122   {
123     return seqstrings;
124   }
125   public String getPointsasCsv(boolean transformed, int xdim, int ydim, int zdim)
126   {
127     StringBuffer csv = new StringBuffer();
128     csv.append("\"Sequence\"");
129     if (transformed)
130     {
131       csv.append(",");
132       csv.append(xdim);
133       csv.append(",");
134       csv.append(ydim);
135       csv.append(",");
136       csv.append(zdim);
137     }
138     else
139     {
140       for (int d = 1, dmax = pca.component(1).length; d <= dmax; d++)
141       {
142         csv.append("," + d);
143       }
144     }
145     csv.append("\n");
146     for (int s = 0; s < seqs.length; s++)
147     {
148       csv.append("\"" + seqs[s].getName() + "\"");
149       double fl[];
150       if (!transformed)
151       {
152         // output pca in correct order
153         fl = pca.component(s);
154         for (int d = fl.length - 1; d >= 0; d--)
155         {
156           csv.append(",");
157           csv.append(fl[d]);
158         }
159       }
160       else
161       {
162         // output current x,y,z coords for points
163         fl = getPointPosition(s);
164         for (int d = 0; d < fl.length; d++)
165         {
166           csv.append(",");
167           csv.append(fl[d]);
168         }
169       }
170       csv.append("\n");
171     }
172     return csv.toString();
173   }
174
175   /**
176    * 
177    * @return x,y,z positions of point s (index into points) under current
178    *         transform.
179    */
180   public double[] getPointPosition(int s)
181   {
182     double pts[] = new double[3];
183     float[] p = points.elementAt(s).coord;
184     pts[0] = p[0];
185     pts[1] = p[1];
186     pts[2] = p[2];
187     return pts;
188   }
189
190 }