Clover icon

Coverage Report

  1. Project Clover database Wed Nov 13 2024 16:12:26 GMT
  2. Package jalview.renderer

File ContactGeometry.java

 

Coverage histogram

../../img/srcFileCovDistChart7.png
29% of files have more coverage

Code metrics

32
60
10
2
312
168
32
0.53
6
5
3.2

Classes

Class Line # Actions
ContactGeometry 39 51 27
0.681818268.2%
ContactGeometry.contactInterval 103 9 5
0.8571428785.7%
 

Contributing tests

This file is covered by 13 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.renderer;
22   
23    import java.util.Arrays;
24    import java.util.Iterator;
25    import java.util.List;
26   
27    import jalview.datamodel.ColumnSelection;
28    import jalview.datamodel.ContactListI;
29    import jalview.datamodel.HiddenColumns;
30    import jalview.renderer.ContactGeometry.contactInterval;
31   
32    /**
33    * encapsulate logic for mapping between positions in a ContactList and their
34    * rendered representation in a given number of pixels.
35    *
36    * @author jprocter
37    *
38    */
 
39    public class ContactGeometry
40    {
41   
42    final ContactListI contacts;
43   
44    /**
45    * how many pixels per contact (1..many)
46    */
47    final int pixels_step;
48   
49    /**
50    * how many contacts per pixel (many > 0)
51    */
52    final double contacts_per_pixel;
53   
54    /**
55    * number of contacts being mapped
56    */
57    final int contact_height;
58   
59    /**
60    * number of pixels to map contact_height to
61    */
62    final int graphHeight;
63   
64    /**
65    * number of contacts for each pixel_step - to last whole contact
66    */
67    final double contacts_step;
68   
69    final int lastStep;
70   
71    /**
72    * Bean used to map from a range of contacts to a range of pixels
73    *
74    * @param contacts
75    * @param graphHeight
76    * Number of pixels to map given range of contacts
77    */
 
78  144859 toggle public ContactGeometry(final ContactListI contacts, int graphHeight)
79    {
80  144859 this.contacts = contacts;
81  144859 this.graphHeight = graphHeight;
82  144859 contact_height = contacts.getContactHeight();
83    // fractional number of contacts covering each pixel
84  144859 contacts_per_pixel = (graphHeight <= 1) ? contact_height
85    : ((double) contact_height) / ((double) graphHeight);
86   
87  144859 if (contacts_per_pixel >= 1)
88    {
89    // many contacts rendered per pixel
90  31824 pixels_step = 1;
91    }
92    else
93    {
94    // pixel height for each contact
95  113035 pixels_step = (int) Math
96    .ceil(((double) graphHeight) / (double) contact_height);
97    }
98  144859 contacts_step = pixels_step * contacts_per_pixel;
99  144859 lastStep = (int) Math.min((double) graphHeight,
100    ((double) graphHeight) / ((double) pixels_step));
101    }
102   
 
103    public class contactInterval
104    {
 
105  147121372 toggle public contactInterval(int cStart, int cEnd, int pStart, int pEnd)
106    {
107  147121373 this.cStart = cStart;
108  147121373 this.cEnd = cEnd;
109  147121373 this.pStart = pStart;
110  147121373 this.pEnd = pEnd;
111    }
112   
113    // range on contact list
114    public final int cStart;
115   
116    public final int cEnd;
117   
118    // range in pixels
119    public final int pStart;
120   
121    public final int pEnd;
122   
 
123  174 toggle @Override
124    public boolean equals(Object obj)
125    {
126  174 if (obj == null || !(obj instanceof contactInterval))
127    {
128  0 return false;
129    }
130  174 contactInterval them = (contactInterval) obj;
131  174 return cStart == them.cStart && cEnd == them.cEnd && pEnd == them.pEnd
132    && pStart == them.pStart;
133    }
134   
 
135  4 toggle @Override
136    public String toString()
137    {
138  4 return "Contacts [" + cStart + "," + cEnd + "] : Pixels [" + pStart
139    + "," + pEnd + "]";
140    }
141    }
142   
143    /**
144    *
145    * @param columnSelection
146    * @param ci
147    * @param visibleOnly
148    * - when true, only test intersection of visible columns given
149    * matrix range
150    * @return true if the range on the matrix specified by ci intersects with
151    * selected columns in the ContactListI's reference frame.
152    */
153   
 
154  139171 toggle boolean intersects(contactInterval ci, ColumnSelection columnSelection,
155    HiddenColumns hiddenColumns, boolean visibleOnly)
156    {
157  139171 boolean rowsel = false;
158  139171 final int[] mappedRange = contacts.getMappedPositionsFor(ci.cStart,
159    ci.cEnd);
160  139170 if (mappedRange == null)
161    {
162  0 return false;
163    }
164  278341 for (int p = 0; p < mappedRange.length && !rowsel; p += 2)
165    {
166  139170 boolean containsHidden = false;
167  139169 if (visibleOnly && hiddenColumns != null
168    && hiddenColumns.hasHiddenColumns())
169    {
170    // TODO: turn into function on hiddenColumns and create test !!
171  0 Iterator<int[]> viscont = hiddenColumns.getVisContigsIterator(
172    -1 + mappedRange[p], -1 + mappedRange[p + 1], false);
173  0 containsHidden = !viscont.hasNext();
174  0 if (!containsHidden)
175    {
176  0 for (int[] interval = viscont.next(); viscont
177    .hasNext(); rowsel |= columnSelection
178    .intersects(interval[p], interval[p + 1]))
179  0 ;
180    }
181    }
182    else
183    {
184  139170 rowsel = columnSelection.intersects(-1 + mappedRange[p],
185    -1 + mappedRange[p + 1]);
186    }
187    }
188  139171 return rowsel;
189   
190    }
191   
192    /**
193    * Return mapped cell intersecting pStart \
194    *
195    * FIXME: REDUNDANT METHOD - COULD DELETE FIXME: OR RE-IMPLEMENT AS EFFICIENT
196    * RANGE QUERY
197    *
198    * @param pStart
199    * [0..)
200    * @param pEnd
201    * @return nearest full cell containing pStart - does not set
202    * contactInterval.pEnd or cEnd to equivalent position on pEnd !
203    */
 
204  84 toggle public contactInterval mapFor(int pStart, int pEnd)
205    {
206  84 if (pStart < 0)
207    {
208  0 pStart = 0;
209    }
210  84 if (pEnd < pStart)
211    {
212  0 pEnd = pStart;
213    }
214  84 if (pEnd >= graphHeight)
215    {
216  4 pEnd = graphHeight - 1;
217    }
218  84 if (pStart >= graphHeight)
219    {
220  0 pStart = graphHeight - pixels_step;
221    }
222  84 int step = Math.floorDiv(pStart, pixels_step);
223  84 return findStep(step);
224    }
225   
226    /**
227    *
228    * @param step
229    * [0..) n steps covering height and contactHeight
230    * @return contactInterval for step, or null if out of bounds
231    */
 
232  147121375 toggle contactInterval findStep(int step)
233    {
234  147121375 if (step < 0 || step > lastStep)
235    {
236  0 return null;
237    }
238  147121375 return new contactInterval((int) Math.floor(contacts_step * step),
239    -1 + (int) Math.min(contact_height,
240    Math.floor(contacts_step * (step + 1))),
241    pixels_step * step,
242    Math.min(graphHeight, (step + 1) * pixels_step) - 1);
243    }
244   
245    /**
246    * return the cell containing given pixel
247    *
248    * @param pCentre
249    * @return range for pCEntre
250    */
 
251  139257 toggle public contactInterval mapFor(int pCentre)
252    {
253  139257 if (pCentre >= graphHeight + pixels_step)
254    {
255  0 return null;
256    }
257  139257 int step = Math.floorDiv(pCentre, pixels_step);
258  139257 return findStep(step);
259    }
260   
 
261  141374 toggle public List<contactInterval> allSteps()
262    {
263  141374 contactInterval[] array = new contactInterval[lastStep + 1];
264  141374 int csum = 0, psum = 0;
265  147123408 for (int i = 0; i <= lastStep; i++)
266    {
267  146982034 array[i] = findStep(i);
268  146982034 csum += 1 + array[i].cEnd - array[i].cStart;
269  146982034 psum += 1 + array[i].pEnd - array[i].pStart;
270    }
271  141374 if (csum != contact_height || psum != graphHeight)
272    {
273  0 System.err.println("csum = " + csum + " not " + contact_height + "\n"
274    + "psum = " + psum + " not " + graphHeight);
275  0 return null;
276    }
277  141374 return Arrays.asList(array);
278    }
279   
 
280  0 toggle public Iterator<contactInterval> iterateOverContactIntervals(
281    int graphHeight)
282    {
283    // NOT YET IMPLEMENTED
284  0 return null;
285    // int cstart = 0, cend;
286    //
287    // for (int ht = y2,
288    // eht = y2 - graphHeight; ht >= eht; ht -= pixels_step)
289    // {
290    // cstart = (int) Math.floor(((double) y2 - ht) * contacts_per_pixel);
291    // cend = (int) Math.min(contact_height,
292    // Math.ceil(cstart + contacts_per_pixel * pixels_step));
293    //
294    // return new Iterator<contactIntervals>() {
295    //
296    // @Override
297    // public boolean hasNext()
298    // {
299    // // TODO Auto-generated method stub
300    // return false;
301    // }
302    //
303    // @Override
304    // public contactIntervals next()
305    // {
306    // // TODO Auto-generated method stub
307    // return null;
308    // }
309    //
310    // }
311    }
312    }