JAL-2349 JAL-3855 ContactListI.getPosition() to recover original position passed...
[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           throws Exception
34   {
35     refSeq = _refSeq;
36     while (refSeq.getDatasetSequence() != null)
37     {
38       refSeq = refSeq.getDatasetSequence();
39     }
40     // convert the lists to primitive arrays and store
41     length = _refSeq.getEnd() - _refSeq.getStart() + 1;
42
43     if (!pae_obj.containsKey("predicted_aligned_error"))
44     {
45       parse_version_1_pAE(pae_obj);
46       return;
47     }
48     else
49     {
50       parse_version_2_pAE(pae_obj);
51     }
52   }
53
54   /**
55    * parse a sane JSON representation of the pAE
56    * 
57    * @param pae_obj
58    */
59   private void parse_version_2_pAE(Map<String, Object> pae_obj)
60   {
61     elements = new float[length][length];
62     // this is never going to be reached by the integer rounding.. or is it ?
63     maxscore = ((Double) pae_obj.get("max_predicted_aligned_error"))
64             .floatValue();
65     Iterator<List<Long>> scoreRows = ((List<List<Long>>) pae_obj
66             .get("predicted_aligned_error")).iterator();
67     int row = 0, col = 0;
68     while (scoreRows.hasNext())
69     {
70       Iterator<Long> scores = scoreRows.next().iterator();
71       while (scores.hasNext())
72       {
73         elements[row][col++] = scores.next();
74       }
75       row++;
76       col = 0;
77     }
78     maxcol = length;
79     maxrow = length;
80   }
81
82   /**
83    * v1 format got ditched 28th July 2022 see
84    * https://alphafold.ebi.ac.uk/faq#:~:text=We%20updated%20the%20PAE%20JSON%20file%20format%20on%2028th%20July%202022
85    * 
86    * @param pae_obj
87    */
88   private void parse_version_1_pAE(Map<String, Object> pae_obj)
89   {
90     // assume indices are with respect to range defined by _refSeq on the
91     // dataset refSeq
92     Iterator<Long> rows = ((List<Long>) pae_obj.get("residue1")).iterator();
93     Iterator<Long> cols = ((List<Long>) pae_obj.get("residue2")).iterator();
94     Iterator<Double> scores = ((List<Double>) pae_obj.get("distance"))
95             .iterator();
96
97     elements = new float[length][length];
98     while (scores.hasNext())
99     {
100       float escore = scores.next().floatValue();
101       int row = rows.next().intValue();
102       int col = cols.next().intValue();
103       if (maxrow < row)
104       {
105         maxrow = row;
106       }
107       if (maxcol < col)
108       {
109         maxcol = col;
110       }
111       elements[row - 1][col - 1] = escore;
112     }
113
114     maxscore = ((Double) pae_obj.get("max_predicted_aligned_error"))
115             .floatValue();
116   }
117
118   @Override
119   public ContactListI getContactList(final int _column)
120   {
121     if (_column < 0 || _column >= elements.length)
122     {
123       return null;
124     }
125
126     return new ContactListImpl(new ContactListProviderI()
127     {
128       @Override
129       public int getPosition()
130       {
131         return _column;
132       }
133
134       @Override
135       public int getContactHeight()
136       {
137         return maxcol - 1;
138       }
139
140       @Override
141       public double getContactAt(int column)
142       {
143         if (column < 0 || column >= elements[_column].length)
144         {
145           return -1;
146         }
147         // TODO Auto-generated method stub
148         return elements[_column][column];
149       }
150     });
151   }
152
153   @Override
154   public float getMin()
155   {
156     return 0;
157   }
158
159   @Override
160   public float getMax()
161   {
162     return maxscore;
163   }
164
165   @Override
166   public boolean hasReferenceSeq()
167   {
168     return (refSeq != null);
169   }
170
171   @Override
172   public SequenceI getReferenceSeq()
173   {
174     return refSeq;
175   }
176
177 }