Clover icon

Coverage Report

  1. Project Clover database Fri Jul 3 2026 14:09:54 BST
  2. Package jalview.ws.datamodel.alphafold

File MappableContactMatrix.java

 
testImportPAEAndStructureForMultiChainSeqs: Couln't create a mapping for this matrix.
 

Coverage histogram

../../../../img/srcFileCovDistChart8.png
21% of files have more coverage

Code metrics

88
137
27
1
544
376
84
0.61
5.07
27
3.11

Classes

Class Line # Actions
MappableContactMatrix 38 137 84
0.7698412577%
 

Contributing tests

This file is covered by 102 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.awt.Color;
24    import java.util.ArrayList;
25    import java.util.BitSet;
26   
27    import jalview.datamodel.ContactListI;
28    import jalview.datamodel.ContactListImpl;
29    import jalview.datamodel.ContactListProviderI;
30    import jalview.datamodel.ContactMatrixI;
31    import jalview.datamodel.GroupSet;
32    import jalview.datamodel.GroupSetI;
33    import jalview.datamodel.Mapping;
34    import jalview.datamodel.SequenceI;
35    import jalview.util.MapList;
36    import jalview.ws.datamodel.MappableContactMatrixI;
37   
 
38    Test failure here public abstract class MappableContactMatrix<T extends MappableContactMatrix<T>>
39    implements MappableContactMatrixI
40    {
41    /**
42    * the matrix that is being mapped to
43    */
44    protected ContactMatrixI mappedMatrix = null;
45   
 
46  5127 toggle public ContactListI getContactList(int column)
47    {
48  5127 return mappedMatrix.getContactList(column);
49    }
50   
 
51  254 toggle public float getMin()
52    {
53  254 return mappedMatrix.getMin();
54    }
55   
 
56  263 toggle public float getMax()
57    {
58  263 return mappedMatrix.getMax();
59    }
60   
 
61  3370 toggle public int getWidth()
62    {
63  3370 return mappedMatrix.getWidth();
64    }
65   
 
66  103457 toggle public int getHeight()
67    {
68  103457 return mappedMatrix.getHeight();
69    }
70   
 
71  0 toggle @Override
72    public ContactMatrixI getMappedMatrix()
73    {
74  0 return mappedMatrix;
75    }
76   
 
77  34058 toggle @Override
78    public GroupSetI getGroupSet()
79    {
80  34058 return mappedMatrix.getGroupSet();
81    };
82   
 
83  2 toggle @Override
84    public void setGroupSet(GroupSet makeGroups)
85    {
86  2 mappedMatrix.setGroupSet(makeGroups);
87    }
88   
89    /**
90    * the sequence and how it is mapped to the matrix
91    */
92   
93    SequenceI refSeq = null;
94   
95    MapList toSeq = null;
96   
97    /**
98    * the length that refSeq is expected to be (excluding gaps, of course)
99    */
100    int length;
101   
 
102  339454 toggle @Override
103    public boolean hasReferenceSeq()
104    {
105  339454 return (refSeq != null);
106    }
107   
 
108  183 toggle @Override
109    public SequenceI getReferenceSeq()
110    {
111  183 return refSeq;
112    }
113   
 
114  29 toggle @Override
115    public MapList getMapFor(SequenceI mapSeq)
116    {
117  29 if (refSeq != null)
118    {
119  41 while (mapSeq != refSeq && mapSeq.getDatasetSequence() != null)
120    {
121  12 mapSeq = mapSeq.getDatasetSequence();
122    }
123  29 if (mapSeq != refSeq)
124    {
125  0 return null;
126    }
127    }
128    else
129    {
130  0 if (mapSeq != null)
131    {
132    // our MapList does not concern this seq
133  0 return null;
134    }
135    }
136   
137  29 return toSeq;
138    }
139   
140    /**
141    * set the reference sequence and construct the mapping between the start-end
142    * positions of given sequence and row/columns of contact matrix
143    *
144    * @param _refSeq
145    */
 
146  281 toggle public void setRefSeq(SequenceI _refSeq)
147    {
148  281 setRefSeq(_refSeq, null);
149    }
 
150  281 toggle public void setRefSeq(SequenceI _refSeq, int[] _refSeq_Range) {
151  281 refSeq = _refSeq;
152  301 while (refSeq.getDatasetSequence() != null)
153    {
154  20 refSeq = refSeq.getDatasetSequence();
155    }
156  281 if (_refSeq_Range == null || _refSeq_Range.length == 0) {
157  281 length = _refSeq.getEnd() - _refSeq.getStart() + 1;
158  281 int from,to;
159  281 from = 0;
160  281 to = length - 1;
161  281 _refSeq_Range = new int[] { from, to };
162    }
163    // if (length!=refSeq.getLength() || _refSeq.getStart()!=1)
164    {
165  281 toSeq = new MapList(
166    new int[]
167    { _refSeq.getStart(), _refSeq.getEnd() },
168    _refSeq_Range, 1, 1);
169    }
170    }
171   
 
172  58 toggle public T liftOver(SequenceI newRefSeq, Mapping sp2sq)
173    {
174  58 if (sp2sq.getMappedWidth() != sp2sq.getWidth())
175    {
176    // TODO: employ getWord/MappedWord to transfer annotation between cDNA and
177    // Protein reference frames
178  0 throw new Error(
179    "liftOver currently not implemented for transfer of annotation between different types of seqeunce");
180    }
181  58 boolean mapIsTo = (sp2sq != null) ? (sp2sq.getTo() == refSeq) : false;
182   
183    /**
184    * map from matrix to toSeq's coordinate frame
185    */
186  58 int[] refMap = toSeq.locateInFrom(0, length - 1);
187  57 if (refMap==null)
188    {
189  0 Test failure here throw new Error("Couln't create a mapping for this matrix.");
190    }
191  57 ArrayList<Integer> newFromMap = new ArrayList<Integer>();
192  57 int last = -1;
193  114 for (int i = 0; i < refMap.length; i += 2)
194    {
195    /*
196    * for each contiguous range in toSeq, locate corresponding range in sequence mapped to toSeq by sp2sq
197    */
198  57 int[] sp2map = mapIsTo
199    ? sp2sq.getMap().locateInFrom(refMap[i], refMap[i + 1])
200    : sp2sq.getMap().locateInTo(refMap[i], refMap[i + 1]);
201  57 if (sp2map == null)
202    {
203  0 continue;
204    }
205   
206  115 for (int spm = 0; spm < sp2map.length; spm += 2)
207    {
208   
209  58 if (last > -1)
210    {
211  1 if (sp2map[spm] != last + 1)
212    {
213  1 newFromMap.add(sp2map[spm]);
214    }
215    else
216    {
217  0 newFromMap.remove(newFromMap.size() - 1);
218    }
219    }
220    else
221    {
222  57 newFromMap.add(sp2map[spm]);
223    }
224  58 last = sp2map[spm + 1];
225  58 newFromMap.add(last);
226    }
227    }
228  57 if ((newFromMap.size() % 2) != 0)
229    {
230    // should have had an even number of int ranges!
231  0 throw new Error("PAEMatrix liftover failed.");
232    }
233  57 int fromIntMap[] = new int[newFromMap.size()];
234  57 int ipos = 0;
235  57 for (Integer i : newFromMap)
236    {
237  116 fromIntMap[ipos++] = i;
238    }
239  57 MapList newFromMapList = new MapList(fromIntMap,
240    new int[]
241    { 0, length - 1 }, 1, 1);
242   
243  57 T newCM = newMappableContactMatrix(newRefSeq, newFromMapList);
244  57 return newCM;
245    }
246   
247    protected abstract T newMappableContactMatrix(SequenceI newRefSeq,
248    MapList newFromMapList);
249   
 
250  5 toggle @Override
251    public int[] getMappedPositionsFor(final SequenceI localFrame,
252    final int column)
253    {
254  5 return getMappedPositionsFor(localFrame, column, column);
255    }
256   
 
257  5 toggle @Override
258    public int[] getMappedPositionsFor(final SequenceI localFrame, int from,
259    int to)
260    {
261  5 if (localFrame == null)
262    {
263  0 throw new Error("Unimplemented when no local sequence given.");
264    }
265  5 SequenceI lf = localFrame, uf = refSeq;
266   
267    // check that localFrame is derived from refSeq
268    // just look for dataset sequences and check they are the same.
269    // in future we could use DBRefMappings/whatever.
270  6 while (lf.getDatasetSequence() != null
271    || uf.getDatasetSequence() != null)
272    {
273  1 if (lf.getDatasetSequence() != null)
274    {
275  1 lf = lf.getDatasetSequence();
276    }
277  1 if (uf.getDatasetSequence() != null)
278    {
279  0 uf = uf.getDatasetSequence();
280    }
281    }
282  5 if (lf != uf)
283    {
284    // could try harder to find a mapping
285  0 throw new Error("This Matrix associated with '" + refSeq.getName()
286    + "' is not mappable for the given localFrame sequence. ("
287    + localFrame.getName() + ")");
288    }
289   
290    // now look up from-to matrix columns in toSeq frame
291   
292  5 if (toSeq == null)
293    {
294    // no mapping - so we assume 1:1
295  0 return new int[] { from, to };
296    }
297    // from-to are matrix columns
298    // first locate on reference sequence
299   
300  5 int[] mappedPositions = toSeq.locateInFrom(from, to);
301  5 if (mappedPositions == null)
302    {
303  2 return null;
304    }
305   
306    // and now map to localFrame
307    // from-to columns on the associated sequence should be
308    // i. restricted to positions in localFrame
309    // ii.
310   
311    // int s = -1, e = -1;
312    // for (int p = 0; p < mappedPositions.length; p++)
313    // {
314    // if (s == -1 && mappedPositions[p] >= localFrame.getStart())
315    // {
316    // s = p; // remember first position within local frame
317    // }
318    // if (e == -1 || mappedPositions[p] <= localFrame.getEnd())
319    // {
320    // // update end pointer
321    // e = p;
322    // // compute local map
323    // mappedPositions[p] = localFrame.findIndex(mappedPositions[p]);
324    // }
325    // }
326    // int[] _trimmed = new int[e - s + 1];
327    // return _trimmed;
328  3 return mappedPositions;
329    }
330   
 
331  8609 toggle @Override
332    public ContactListI getMappableContactList(final SequenceI localFrame,
333    final int column)
334    {
335  8609 final int _column;
336  8609 final int _lcolumn;
337  8609 if (localFrame == null)
338    {
339  0 throw new Error("Unimplemented when no local sequence given.");
340    }
341    // return a ContactListI for column
342    // column is index into localFrame
343    // 1. map column to corresponding column in matrix
344  8609 final MappableContactMatrix us = this;
345  8609 _lcolumn = localFrame.findPosition(column);
346   
347  8609 if (toSeq != null)
348    {
349  8609 SequenceI lf = localFrame, uf = refSeq;
350   
351    // just look for dataset sequences and check they are the same.
352    // in future we could use DBRefMappings/whatever.
353  17098 while (lf.getDatasetSequence() != null
354    || uf.getDatasetSequence() != null)
355    {
356  8489 if (lf.getDatasetSequence() != null)
357    {
358  8489 lf = lf.getDatasetSequence();
359    }
360  8489 if (uf.getDatasetSequence() != null)
361    {
362  2 uf = uf.getDatasetSequence();
363    }
364    }
365  8609 if (lf != uf)
366    {
367    // could try harder to find a mapping
368  0 throw new Error("This Matrix associated with '" + refSeq.getName()
369    + "' is not mappable for the given localFrame sequence. ("
370    + localFrame.getName() + ")");
371    }
372    // check the mapping to see if localFrame _lcolumn exists
373  8609 int[] word = toSeq.locateInTo(_lcolumn, _lcolumn);
374  8609 if (word == null)
375    {
376  11 return null;
377    }
378  8598 _column = word[0];
379    }
380    else
381    {
382    // no mapping
383  0 _column = _lcolumn;
384    }
385   
386    // TODO - remove ? this may be a redundant check
387  8598 if (_column < 0 || ((toSeq != null && _column > toSeq.getToHighest())
388    || (toSeq == null && getHeight() <= _column)))
389    {
390  0 return null;
391    }
392   
393    // 2. resolve ranges in matrix corresponding to range in localFrame
394  8598 final int[] matrixRange = toSeq == null
395    ? new int[]
396    { localFrame.getStart(), localFrame.getEnd() }
397    : toSeq.locateInTo(localFrame.getStart(), localFrame.getEnd());
398   
399  8598 int h = 0;
400  17196 for (int p = 0; p < matrixRange.length; p += 2)
401    {
402  8598 h += 1 + Math.abs(matrixRange[p + 1] - matrixRange[p]);
403    }
404  8598 final int rangeHeight = h;
405    // 3. Construct ContactListImpl instance for just those segments.
406   
407  8598 return new ContactListImpl(new ContactListProviderI()
408    {
409   
 
410  0 toggle public int getColumn()
411    {
412  0 return column;
413    }
414   
 
415  0 toggle @Override
416    public int getPosition()
417    {
418  0 return _column;
419    }
420   
 
421  489181 toggle @Override
422    public int getContactHeight()
423    {
424  489181 return rangeHeight;
425    }
426   
 
427  2846704 toggle @Override
428    public double getContactAt(int mcolumn)
429    {
430  2846704 if (mcolumn < 0 || mcolumn >= rangeHeight)
431    {
432  0 return -1;
433    }
434  2846704 return getElementAt(_column, locateInRange(mcolumn));
435   
436    // this code maps from mcolumn to localFrame - but that isn't what's
437    // needed
438    // int loccolumn = localFrame.findPosition(mcolumn);
439    // int[] lcolumn=(toSeq==null) ? new int[] {mcolumn} :
440    // toSeq.locateInTo(loccolumn,loccolumn);
441    // if (lcolumn==null || lcolumn[0] < 0 || lcolumn[0] >= rangeHeight)
442    // {
443    // return -1;
444    // }
445    // return getElementAt(_column,lcolumn[0]);
446    }
447   
 
448  339270 toggle @Override
449    public int[] getMappedPositionsFor(int cStart, int cEnd)
450    {
451  339269 if (!hasReferenceSeq())
452    {
453  0 return ContactListProviderI.super.getMappedPositionsFor(cStart,
454    cEnd);
455    }
456    // map into segment of matrix being shown
457  339269 int realCstart = locateInRange(cStart);
458  339267 int realCend = locateInRange(cEnd);
459   
460    // TODO account for discontinuities in the mapping
461   
462  339265 int[] mappedPositions = toSeq.locateInFrom(realCstart, realCend);
463  339265 if (mappedPositions != null)
464    {
465  339265 int s = -1, e = -1;
466  1017811 for (int p = 0; p < mappedPositions.length; p++)
467    {
468  678543 if (s == -1 && mappedPositions[p] >= localFrame.getStart())
469    {
470  339265 s = p; // remember first position within local frame
471    }
472  678536 if (e == -1 || mappedPositions[p] <= localFrame.getEnd())
473    {
474    // update end pointer
475  678536 e = p;
476    // compute local map
477  678537 mappedPositions[p] = localFrame.findIndex(mappedPositions[p]);
478    }
479    }
480    }
481  339273 return mappedPositions;
482    }
483   
484    /**
485    * @return the mcolumn'th position in the matrixRange window on the matrix
486    */
 
487  3525008 toggle private int locateInRange(int mcolumn)
488    {
489   
490  3525007 int h = 0, p = 0;
491  3525008 while (h < mcolumn && p + 2 < matrixRange.length)
492    {
493  0 h += 1 + Math.abs(matrixRange[p + 1] - matrixRange[p]);
494  0 p += 2;
495    }
496  3525008 return matrixRange[p] + mcolumn - h;
497    }
498   
 
499  8481 toggle @Override
500    public Color getColourForGroup()
501    {
502  8481 BitSet gp = us.getGroupsFor(_column);
503  8481 Color col = us.getColourForGroup(gp);
504  8481 return col;
505    }
506    });
507    }
508   
509    /**
510    * get a specific element of the underlying contact matrix in its data-local
511    * coordinates rather than the mapped frame. Implementations are allowed to
512    * throw RunTimeExceptions if _column/i are out of bounds
513    *
514    * @param _column
515    * @param i
516    * @return
517    */
 
518  2846626 toggle public double getElementAt(int _column, int i)
519    {
520  2846626 return mappedMatrix.getElementAt(_column, i);
521    }
522   
 
523  120 toggle @Override
524    public int hashCode()
525    {
526  120 return 7 * (refSeq != null ? refSeq.hashCode() : 0)
527  120 + 11 * (toSeq != null ? toSeq.hashCode() : 0)
528  120 + 13 * (mappedMatrix != null ? mappedMatrix.hashCode() : 0)
529    + length * 3;
530    }
531   
 
532  30 toggle @Override
533    public boolean equals(Object obj)
534    {
535  30 if (obj == null || !(obj.getClass().equals(getClass())))
536    {
537  0 return false;
538    }
539  30 T them = (T) obj;
540  30 return mappedMatrix == them.mappedMatrix && length == them.length
541    && refSeq == them.refSeq && toSeq.equals(them.toSeq);
542   
543    }
544    }