JAL-629 implementation of --tempfac options
[jalview.git] / src / jalview / ws / datamodel / alphafold / PAEContactMatrix.java
1 package jalview.ws.datamodel.alphafold;
2
3 import java.util.Iterator;
4 import java.util.List;
5 import java.util.Map;
6
7 import jalview.datamodel.ContactListI;
8 import jalview.datamodel.ContactListImpl;
9 import jalview.datamodel.ContactListProviderI;
10 import jalview.datamodel.ContactMatrixI;
11 import jalview.datamodel.SequenceI;
12
13 public class PAEContactMatrix implements ContactMatrixI
14 {
15
16   SequenceI refSeq = null;
17
18   /**
19    * the length that refSeq is expected to be (excluding gaps, of course)
20    */
21   int length;
22
23   int maxrow = 0, maxcol = 0;
24
25   int[] indices1, indices2;
26
27   float[][] elements;
28
29   float maxscore;
30
31   @SuppressWarnings("unchecked")
32   public PAEContactMatrix(SequenceI _refSeq, Map<String, Object> pae_obj)
33   {
34     refSeq = _refSeq;
35     while (refSeq.getDatasetSequence() != null)
36     {
37       refSeq = refSeq.getDatasetSequence();
38     }
39     // convert the lists to primitive arrays and store
40     length = _refSeq.getEnd() - _refSeq.getStart() + 1;
41
42     if (!pae_obj.containsKey("predicted_aligned_error"))
43     {
44       parse_version_1_pAE(pae_obj);
45       return;
46     }
47     else
48     {
49       parse_version_2_pAE(pae_obj);
50     }
51   }
52
53   /**
54    * parse a sane JSON representation of the pAE
55    * 
56    * @param pae_obj
57    */
58   private void parse_version_2_pAE(Map<String, Object> pae_obj)
59   {
60     elements = new float[length][length];
61     // this is never going to be reached by the integer rounding.. or is it ?
62     maxscore = ((Double) pae_obj.get("max_predicted_aligned_error"))
63             .floatValue();
64     Iterator<List<Long>> scoreRows = ((List<List<Long>>) pae_obj
65             .get("predicted_aligned_error")).iterator();
66     int row = 0, col = 0;
67     while (scoreRows.hasNext())
68     {
69       Iterator<Long> scores = scoreRows.next().iterator();
70       while (scores.hasNext())
71       {
72         elements[row][col++] = scores.next();
73       }
74       row++;
75       col = 0;
76     }
77     maxcol = length;
78     maxrow = length;
79   }
80
81   /**
82    * v1 format got ditched 28th July 2022 see
83    * https://alphafold.ebi.ac.uk/faq#:~:text=We%20updated%20the%20PAE%20JSON%20file%20format%20on%2028th%20July%202022
84    * 
85    * @param pae_obj
86    */
87   private void parse_version_1_pAE(Map<String, Object> pae_obj)
88   {
89     // assume indices are with respect to range defined by _refSeq on the
90     // dataset refSeq
91     Iterator<Long> rows = ((List<Long>) pae_obj.get("residue1")).iterator();
92     Iterator<Long> cols = ((List<Long>) pae_obj.get("residue2")).iterator();
93     Iterator<Double> scores = ((List<Double>) pae_obj.get("distance"))
94             .iterator();
95
96     elements = new float[length][length];
97     while (scores.hasNext())
98     {
99       float escore = scores.next().floatValue();
100       int row = rows.next().intValue();
101       int col = cols.next().intValue();
102       if (maxrow < row)
103       {
104         maxrow = row;
105       }
106       if (maxcol < col)
107       {
108         maxcol = col;
109       }
110       elements[row - 1][col - 1] = escore;
111     }
112
113     maxscore = ((Double) pae_obj.get("max_predicted_aligned_error"))
114             .floatValue();
115   }
116
117   @Override
118   public ContactListI getContactList(final int _column)
119   {
120     if (_column < 0 || _column >= elements.length)
121     {
122       return null;
123     }
124
125     return new ContactListImpl(new ContactListProviderI()
126     {
127       @Override
128       public int getPosition()
129       {
130         return _column;
131       }
132
133       @Override
134       public int getContactHeight()
135       {
136         return maxcol - 1;
137       }
138
139       @Override
140       public double getContactAt(int column)
141       {
142         if (column < 0 || column >= elements[_column].length)
143         {
144           return -1;
145         }
146         // TODO Auto-generated method stub
147         return elements[_column][column];
148       }
149     });
150   }
151
152   @Override
153   public float getMin()
154   {
155     return 0;
156   }
157
158   @Override
159   public float getMax()
160   {
161     return maxscore;
162   }
163
164   @Override
165   public boolean hasReferenceSeq()
166   {
167     return (refSeq != null);
168   }
169
170   @Override
171   public SequenceI getReferenceSeq()
172   {
173     return refSeq;
174   }
175
176   @Override
177   public String getAnnotDescr()
178   {
179     return "Predicted Alignment Error for " + refSeq.getName();
180   }
181
182   @Override
183   public String getAnnotLabel()
184   {
185     return "pAE Matrix";
186   }
187 }