Clover icon

Coverage Report

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

File MappableContactMatrix.java

 

Coverage histogram

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

Code metrics

84
129
26
1
532
364
80
0.62
4.96
26
3.08

Classes

Class Line # Actions
MappableContactMatrix 38 129 80
0.7698744577%
 

Contributing tests

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