JAL-3855 pAE v2 import
[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   }
79
80   /**
81    * v1 format got ditched 28th July 2022 see
82    * https://alphafold.ebi.ac.uk/faq#:~:text=We%20updated%20the%20PAE%20JSON%20file%20format%20on%2028th%20July%202022
83    * 
84    * @param pae_obj
85    */
86   private void parse_version_1_pAE(Map<String, Object> pae_obj)
87   {
88     // assume indices are with respect to range defined by _refSeq on the
89     // dataset refSeq
90     Iterator<Long> rows = ((List<Long>) pae_obj.get("residue1")).iterator();
91     Iterator<Long> cols = ((List<Long>) pae_obj.get("residue2")).iterator();
92     Iterator<Double> scores = ((List<Double>) pae_obj.get("distance"))
93             .iterator();
94
95     elements = new float[length][length];
96     while (scores.hasNext())
97     {
98       float escore = scores.next().floatValue();
99       int row = rows.next().intValue();
100       int col = cols.next().intValue();
101       if (maxrow < row)
102       {
103         maxrow = row;
104       }
105       if (maxcol < col)
106       {
107         maxcol = col;
108       }
109       elements[row - 1][col - 1] = escore;
110     }
111
112     maxscore = ((Double) pae_obj.get("max_predicted_aligned_error"))
113             .floatValue();
114   }
115
116   @Override
117   public ContactListI getContactList(final int _column)
118   {
119     if (_column < 0 || _column >= elements.length)
120     {
121       return null;
122     }
123
124     return new ContactListImpl(new ContactListProviderI()
125     {
126       @Override
127       public int getContactHeight()
128       {
129         return maxcol - 1;
130       }
131
132       @Override
133       public double getContactAt(int column)
134       {
135         if (column < 0 || column >= elements[_column].length)
136         {
137           return -1;
138         }
139         // TODO Auto-generated method stub
140         return elements[_column][column];
141       }
142     });
143   }
144
145   @Override
146   public float getMin()
147   {
148     return 0;
149   }
150
151   @Override
152   public float getMax()
153   {
154     return maxscore;
155   }
156
157   @Override
158   public boolean hasReferenceSeq()
159   {
160     return (refSeq != null);
161   }
162
163   @Override
164   public SequenceI getReferenceSeq()
165   {
166     return refSeq;
167   }
168
169 }