Clover icon

Coverage Report

  1. Project Clover database Mon Sep 2 2024 17:57:51 BST
  2. Package jalview.ws.datamodel.alphafold

File PAEContactMatrix.java

 

Coverage histogram

../../../../img/srcFileCovDistChart9.png
13% of files have more coverage

Code metrics

24
75
14
1
302
206
29
0.39
5.36
14
2.07

Classes

Class Line # Actions
PAEContactMatrix 60 75 29
0.814159381.4%
 

Contributing tests

This file is covered by 37 tests. .

Source view

1    /*
2    * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3    * Copyright (C) $$Year-Rel$$ The Jalview Authors
4    *
5    * This file is part of Jalview.
6    *
7    * Jalview is free software: you can redistribute it and/or
8    * modify it under the terms of the GNU General Public License
9    * as published by the Free Software Foundation, either version 3
10    * of the License, or (at your option) any later version.
11    *
12    * Jalview is distributed in the hope that it will be useful, but
13    * WITHOUT ANY WARRANTY; without even the implied warranty
14    * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15    * PURPOSE. See the GNU General Public License for more details.
16    *
17    * You should have received a copy of the GNU General Public License
18    * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19    * The Jalview Authors are detailed in the 'AUTHORS' file.
20    */
21    package jalview.ws.datamodel.alphafold;
22   
23    import java.io.File;
24    import java.io.FileInputStream;
25    import java.io.IOException;
26    import java.util.Iterator;
27    import java.util.List;
28    import java.util.Map;
29   
30    import org.json.simple.JSONObject;
31   
32    import jalview.datamodel.ContactListI;
33    import jalview.datamodel.ContactListImpl;
34    import jalview.datamodel.ContactListProviderI;
35    import jalview.datamodel.ContactMatrixI;
36    import jalview.datamodel.FloatContactMatrix;
37    import jalview.datamodel.GroupSet;
38    import jalview.datamodel.SequenceDummy;
39    import jalview.datamodel.SequenceI;
40    import jalview.io.FileFormatException;
41    import jalview.util.MapList;
42    import jalview.util.MapUtils;
43    import jalview.ws.dbsources.EBIAlfaFold;
44   
45    /**
46    * routines and class for holding predicted alignment error matrices as produced
47    * by alphafold et al.
48    *
49    * getContactList(column) returns the vector of predicted alignment errors for
50    * reference position given by column getElementAt(column, i) returns the
51    * predicted superposition error for the ith position when column is used as
52    * reference
53    *
54    * Many thanks to Ora Schueler Furman for noticing that earlier development
55    * versions did not show the PAE oriented correctly
56    *
57    * @author jprocter
58    *
59    */
 
60    public class PAEContactMatrix extends
61    MappableContactMatrix<PAEContactMatrix> implements ContactMatrixI
62    {
63   
 
64  49 toggle @SuppressWarnings("unchecked")
65    public PAEContactMatrix(SequenceI _refSeq, Map<String, Object> pae_obj)
66    throws FileFormatException
67    {
68  49 setRefSeq(_refSeq);
69    // convert the lists to primitive arrays and store
70   
71  49 if (!MapUtils.containsAKey(pae_obj, "predicted_aligned_error", "pae"))
72    {
73  2 parse_version_1_pAE(pae_obj);
74  2 return;
75    }
76    else
77    {
78  47 parse_version_2_pAE(pae_obj);
79    }
80    }
81   
82    /**
83    * construct a sequence associated PAE matrix directly from a float array
84    *
85    * @param _refSeq
86    * @param matrix
87    */
 
88  6 toggle public PAEContactMatrix(SequenceI _refSeq, float[][] matrix)
89    {
90  6 mappedMatrix = new FloatContactMatrix(matrix);
91  6 setRefSeq(_refSeq);
92    }
93   
94    /**
95    * new matrix with specific mapping to a reference sequence
96    *
97    * @param newRefSeq
98    * @param newFromMapList
99    * @param elements2
100    * @param grps2
101    */
 
102  1 toggle public PAEContactMatrix(SequenceI newRefSeq, MapList newFromMapList,
103    float[][] elements2, GroupSet grps2)
104    {
105  1 this(newRefSeq, new FloatContactMatrix(elements2, grps2));
106  1 toSeq = newFromMapList;
107    }
108   
 
109  1 toggle public PAEContactMatrix(SequenceI _refSeq,
110    ContactMatrixI floatContactMatrix)
111    {
112  1 mappedMatrix = floatContactMatrix;
113  1 setRefSeq(_refSeq);
114    }
115   
 
116  42 toggle public PAEContactMatrix(SequenceI _refSeq, MapList newFromMapList,
117    ContactMatrixI floatContactMatrix)
118    {
119  42 mappedMatrix = floatContactMatrix;
120  42 setRefSeq(_refSeq);
121  42 toSeq = newFromMapList;
122    }
123   
 
124  39 toggle @Override
125    protected PAEContactMatrix newMappableContactMatrix(SequenceI newRefSeq,
126    MapList newFromMapList)
127    {
128  39 return new PAEContactMatrix(newRefSeq, newFromMapList, mappedMatrix);
129    }
130   
131    /**
132    * parse a sane JSON representation of the pAE and update the mappedMatrix
133    *
134    * @param pae_obj
135    */
 
136  47 toggle @SuppressWarnings("unchecked")
137    private void parse_version_2_pAE(Map<String, Object> pae_obj)
138    {
139  47 float maxscore = -1;
140    // look for a maxscore element - if there is one...
141  47 try
142    {
143    // this is never going to be reached by the integer rounding.. or is it ?
144  47 maxscore = ((Double) MapUtils.getFirst(pae_obj,
145    "max_predicted_aligned_error", "max_pae")).floatValue();
146    } catch (Throwable t)
147    {
148    // ignore if a key is not found.
149    }
150  47 List<List<Long>> scoreRows = ((List<List<Long>>) MapUtils
151    .getFirst(pae_obj, "predicted_aligned_error", "pae"));
152  47 float[][] elements = new float[scoreRows.size()][scoreRows.size()];
153  47 int row = 0, col = 0;
154  47 for (List<Long> scoreRow : scoreRows)
155    {
156  8589 Iterator<Long> scores = scoreRow.iterator();
157  3898692 while (scores.hasNext())
158    {
159  3890103 Object d = scores.next();
160  3890103 if (d instanceof Double)
161    {
162  52215 elements[col][row] = ((Double) d).longValue();
163    }
164    else
165    {
166  3837888 elements[col][row] = (float) ((Long) d).longValue();
167    }
168   
169  3890103 if (maxscore < elements[col][row])
170    {
171  0 maxscore = elements[col][row];
172    }
173  3890103 col++;
174    }
175  8589 row++;
176  8589 col = 0;
177    }
178  47 mappedMatrix = new FloatContactMatrix(elements);
179    }
180   
181    /**
182    * v1 format got ditched 28th July 2022 see
183    * https://alphafold.ebi.ac.uk/faq#:~:text=We%20updated%20the%20PAE%20JSON%20file%20format%20on%2028th%20July%202022
184    *
185    * @param pae_obj
186    */
 
187  2 toggle @SuppressWarnings("unchecked")
188    private void parse_version_1_pAE(Map<String, Object> pae_obj)
189    {
190    // assume indices are with respect to range defined by _refSeq on the
191    // dataset refSeq
192  2 Iterator<Long> rows = ((List<Long>) pae_obj.get("residue1")).iterator();
193  2 Iterator<Long> cols = ((List<Long>) pae_obj.get("residue2")).iterator();
194    // two pass - to allocate the elements array
195   
196  2 int maxrow = -1, maxcol = -1;
197  6964 while (rows.hasNext())
198    {
199  6962 int row = rows.next().intValue();
200  6962 int col = cols.next().intValue();
201  6962 if (maxrow < row)
202    {
203  118 maxrow = row;
204    }
205  6962 if (maxcol < col)
206    {
207  118 maxcol = col;
208    }
209   
210    }
211  2 rows = ((List<Long>) pae_obj.get("residue1")).iterator();
212  2 cols = ((List<Long>) pae_obj.get("residue2")).iterator();
213  2 Iterator<Double> scores = ((List<Double>) pae_obj.get("distance"))
214    .iterator();
215  2 float[][] elements = new float[maxcol][maxrow];
216  6964 while (scores.hasNext())
217    {
218  6962 float escore = scores.next().floatValue();
219  6962 int row = rows.next().intValue();
220  6962 int col = cols.next().intValue();
221  6962 if (maxrow < row)
222    {
223  0 maxrow = row;
224    }
225  6962 if (maxcol < col)
226    {
227  0 maxcol = col;
228    }
229  6962 elements[col - 1][row - 1] = escore;
230    }
231   
232  2 mappedMatrix = new FloatContactMatrix(elements);
233    }
234   
 
235  55 toggle @Override
236    public String getAnnotDescr()
237    {
238  55 return "Predicted Alignment Error"
239  55 + ((refSeq == null) ? "" : (" for " + refSeq.getName()));
240    }
241   
 
242  55 toggle @Override
243    public String getAnnotLabel()
244    {
245  55 StringBuilder label = new StringBuilder("PAE Matrix");
246    // if (this.getReferenceSeq() != null)
247    // {
248    // label.append(":").append(this.getReferenceSeq().getDisplayId(false));
249    // }
250  55 return label.toString();
251    }
252   
253    public static final String PAEMATRIX = "PAE_MATRIX";
254   
 
255  122 toggle @Override
256    public String getType()
257    {
258  122 return PAEMATRIX;
259    }
260   
 
261  0 toggle public static void validateContactMatrixFile(String fileName)
262    throws FileFormatException, IOException
263    {
264  0 FileInputStream infile = null;
265  0 try
266    {
267  0 infile = new FileInputStream(new File(fileName));
268    } catch (Throwable t)
269    {
270  0 new IOException("Couldn't open " + fileName, t);
271    }
272  0 JSONObject paeDict = null;
273  0 try
274    {
275  0 paeDict = EBIAlfaFold.parseJSONtoPAEContactMatrix(infile);
276    } catch (Throwable t)
277    {
278  0 new FileFormatException("Couldn't parse " + fileName
279    + " as a JSON dict or array containing a dict");
280    }
281   
282  0 PAEContactMatrix matrix = new PAEContactMatrix(
283    new SequenceDummy("Predicted"), (Map<String, Object>) paeDict);
284  0 if (matrix.getWidth() <= 0)
285    {
286  0 throw new FileFormatException(
287    "No data in PAE matrix read from '" + fileName + "'");
288    }
289    }
290   
 
291  1 toggle @Override
292    public boolean equals(Object obj)
293    {
294  1 return super.equals(obj);
295    }
296   
 
297  33 toggle @Override
298    public int hashCode()
299    {
300  33 return super.hashCode();
301    }
302    }