JAL-2349 JAL-2382 contact matrix datamodel object
[jalview.git] / src / jalview / datamodel / ContactMatrix.java
1 package jalview.datamodel;
2
3 import jalview.ws.params.InvalidArgumentException;
4
5 import java.awt.Color;
6 import java.util.ArrayList;
7 import java.util.List;
8
9 public class ContactMatrix implements ContactMatrixI
10 {
11   /**
12    * are contacts reflexive ?
13    */
14   boolean symmetric = true;
15
16   public ContactMatrix(boolean symmetric)
17   {
18     this.symmetric = symmetric;
19   }
20
21   List<List<Float>> contacts = null;
22
23   int width = 0, numcontacts = 0;
24
25   float min = 0f, max = 0f;
26
27   public void addContact(int left, int right, float strength)
28   {
29     if (left < 0 || right < 0)
30     {
31       throw new Error(new InvalidArgumentException(
32               "Cannot have negative indices for contact left=" + left
33                       + " right=" + right + " strength=" + strength));
34     }
35     if (symmetric)
36     {
37       if (left > right)
38       {
39         // swap
40         int r = right;
41         right = left;
42         left = r;
43       }
44     }
45     if (contacts == null)
46     {
47       // TODO: use sparse list for efficiency ?
48       contacts = new ArrayList<List<Float>>();
49     }
50     List<Float> clist = contacts.get(left);
51     if (clist == null)
52     {
53       clist = new ArrayList<Float>();
54       contacts.set(left, clist);
55     }
56     Float last = clist.set(right, strength);
57     // TODO: if last is non null, may need to recompute range
58     checkBounds(strength);
59     if (last == null)
60     {
61       numcontacts++;
62     }
63   }
64
65   private void checkBounds(float strength)
66   {
67     if (min > strength)
68     {
69       min = strength;
70     }
71     if (max < strength)
72     {
73       max = strength;
74     }
75   }
76
77   Color minColor = Color.white, maxColor = Color.magenta;
78
79   Color shadeFor(float value)
80   {
81     return jalview.util.ColorUtils.getGraduatedColour(value, 0,
82             Color.white, max, Color.magenta);
83   }
84   @Override
85   public ContactListI getContactList(final int column)
86   {
87     if (column < 0 || column >= width)
88     {
89       return null;
90     }
91     return new ContactListI()
92     {
93       int p = column;
94
95       @Override
96       public Color getColorForScore(int column)
97       {
98
99         return shadeFor((float) getContactAt(column));
100       }
101
102       @Override
103       public Color getColorForRange(int i, int j)
104       {
105         double contc;
106         double v = 0;
107         for (int r=i;r<j;r++)
108         {
109           contc = getContactAt(r);
110           if (contc != contc)
111           {
112             v += contc;
113           }
114         }
115         // average for moment - probably more interested in maxIntProj though
116         return shadeFor(((float) v) / (j - i + 1));
117       }
118
119       @Override
120       public int getColumnWidth()
121       {
122         return 1;
123       }
124
125       @Override
126       public int getContactHeight()
127       {
128         return width;
129
130       }
131
132       @Override
133       public double getContactAt(int column)
134       {
135         List<Float> clist;
136         Float cl = null;
137         if (symmetric)
138         {
139           if (p < column)
140           {
141             clist = contacts.get(p);
142             cl = clist.get(column);
143           }
144           else
145           {
146             clist = contacts.get(column);
147             cl = clist.get(p);
148           }
149         }
150         else
151         {
152           clist = contacts.get(p);
153           cl = clist.get(column);
154         }
155         if (cl == null)
156         {
157           // return 0 not NaN ?
158           return Double.NaN;
159         }
160         return cl.doubleValue();
161       }
162     };
163   }
164
165 }