index number for contiguous part of mapped sequence feature
[jalview.git] / src / jalview / datamodel / Mapping.java
1 package jalview.datamodel;
2
3 import java.util.Vector;
4
5 import jalview.util.MapList;
6
7 public class Mapping
8 {
9   /**
10    * Contains the start-end pairs mapping from the associated sequence to the
11    * sequence in the database coordinate system it also takes care of step
12    * difference between coordinate systems
13    */
14   MapList map = null;
15
16   /**
17    * The seuqence that map maps the associated seuqence to (if any).
18    */
19   SequenceI to = null;
20
21   public Mapping(MapList map)
22   {
23     super();
24     this.map = map;
25   }
26
27   public Mapping(SequenceI to, MapList map)
28   {
29     this(map);
30     this.to = to;
31   }
32
33   /**
34    * create a new mapping from
35    * 
36    * @param to
37    *          the sequence being mapped
38    * @param exon
39    *          int[] {start,end,start,end} series on associated sequence
40    * @param is
41    *          int[] {start,end,...} ranges on the reference frame being mapped
42    *          to
43    * @param i
44    *          step size on associated sequence
45    * @param j
46    *          step size on mapped frame
47    */
48   public Mapping(SequenceI to, int[] exon, int[] is, int i, int j)
49   {
50     this(to, new MapList(exon, is, i, j));
51   }
52
53   /**
54    * create a duplicate (and independent) mapping object with the same reference
55    * to any SequenceI being mapped to.
56    * 
57    * @param map2
58    */
59   public Mapping(Mapping map2)
60   {
61     if (map2 != this && map2 != null)
62     {
63       if (map2.map != null)
64       {
65         map = new MapList(map2.map);
66       }
67       to = map2.to;
68     }
69   }
70
71   /**
72    * @return the map
73    */
74   public MapList getMap()
75   {
76     return map;
77   }
78
79   /**
80    * @param map
81    *          the map to set
82    */
83   public void setMap(MapList map)
84   {
85     this.map = map;
86   }
87
88   /**
89    * Equals that compares both the to references and MapList mappings.
90    * 
91    * @param other
92    * @return
93    */
94   public boolean equals(Mapping other)
95   {
96     if (other == null)
97       return false;
98     if (other == this)
99       return true;
100     if (other.to != to)
101       return false;
102     if ((map != null && other.map == null)
103             || (map == null && other.map != null))
104       return false;
105     if (map.equals(other.map))
106       return true;
107     return false;
108   }
109
110   /**
111    * get the 'initial' position in the associated sequence for a position in the
112    * mapped reference frame
113    * 
114    * @param mpos
115    * @return
116    */
117   public int getPosition(int mpos)
118   {
119     if (map != null)
120     {
121       int[] mp = map.shiftTo(mpos);
122       if (mp != null)
123       {
124         return mp[0];
125       }
126     }
127     return mpos;
128   }
129
130   /**
131    * gets boundary in direction of mapping
132    * 
133    * @param position
134    *          in mapped reference frame
135    * @return int{start, end} positions in associated sequence (in direction of
136    *         mapped word)
137    */
138   public int[] getWord(int mpos)
139   {
140     if (map != null)
141     {
142       return map.getToWord(mpos);
143     }
144     return null;
145   }
146
147   /**
148    * width of mapped unit in associated sequence
149    * 
150    */
151   public int getWidth()
152   {
153     if (map != null)
154     {
155       return map.getFromRatio();
156     }
157     return 1;
158   }
159
160   /**
161    * width of unit in mapped reference frame
162    * 
163    * @return
164    */
165   public int getMappedWidth()
166   {
167     if (map != null)
168     {
169       return map.getToRatio();
170     }
171     return 1;
172   }
173
174   /**
175    * get mapped position in the associated reference frame for position pos in
176    * the associated sequence.
177    * 
178    * @param pos
179    * @return
180    */
181   public int getMappedPosition(int pos)
182   {
183     if (map != null)
184     {
185       int[] mp = map.shiftFrom(pos);
186       if (mp != null)
187       {
188         return mp[0];
189       }
190     }
191     return pos;
192   }
193
194   public int[] getMappedWord(int pos)
195   {
196     if (map != null)
197     {
198       int[] mp = map.shiftFrom(pos);
199       if (mp != null)
200       {
201         return new int[]
202         { mp[0], mp[0] + mp[2] * (map.getToRatio() - 1) };
203       }
204     }
205     return null;
206   }
207
208   /**
209    * locates the region of feature f in the associated sequence's reference
210    * frame
211    * 
212    * @param f
213    * @return one or more features corresponding to f
214    */
215   public SequenceFeature[] locateFeature(SequenceFeature f)
216   {
217     if (true)
218     { // f.getBegin()!=f.getEnd()) {
219       if (map != null)
220       {
221         int[] frange = map.locateInFrom(f.getBegin(), f.getEnd());
222         if (frange==null)
223         {
224           // JBPNote - this isprobably not the right thing to doJBPHack
225           return null;
226         }
227         SequenceFeature[] vf = new SequenceFeature[frange.length / 2];
228         for (int i = 0, v = 0; i < frange.length; i += 2, v++)
229         {
230           vf[v] = new SequenceFeature(f);
231           vf[v].setBegin(frange[i]);
232           vf[v].setEnd(frange[i + 1]);
233           if (frange.length > 2)
234             vf[v].setDescription(f.getDescription() + "\nPart " + (v+1));
235         }
236         return vf;
237       }
238     }
239     if (false) // else
240     {
241       int[] word = getWord(f.getBegin());
242       if (word[0] < word[1])
243       {
244         f.setBegin(word[0]);
245       }
246       else
247       {
248         f.setBegin(word[1]);
249       }
250       word = getWord(f.getEnd());
251       if (word[0] > word[1])
252       {
253         f.setEnd(word[0]);
254       }
255       else
256       {
257         f.setEnd(word[1]);
258       }
259     }
260     // give up and just return the feature.
261     return new SequenceFeature[]
262     { f };
263   }
264
265   /**
266    * return a series of contigs on the associated sequence corresponding to the
267    * from,to interval on the mapped reference frame
268    * 
269    * @param from
270    * @param to
271    * @return int[] { from_i, to_i for i=1 to n contiguous regions in the
272    *         associated sequence}
273    */
274   public int[] locateRange(int from, int to)
275   {
276     if (map != null)
277     {
278       if (from <= to)
279       {
280         from = (map.getToLowest() < from) ? from : map.getToLowest();
281         to = (map.getToHighest() > to) ? to : map.getToHighest();
282         if (from > to)
283           return null;
284       }
285       else
286       {
287         from = (map.getToHighest() > from) ? from : map.getToHighest();
288         to = (map.getToLowest() < to) ? to : map.getToLowest();
289         if (from < to)
290           return null;
291       }
292       return map.locateInFrom(from, to);
293     }
294     return new int[]
295     { from, to };
296   }
297
298   /**
299    * return a series of mapped contigs mapped from a range on the associated
300    * sequence
301    * 
302    * @param from
303    * @param to
304    * @return
305    */
306   public int[] locateMappedRange(int from, int to)
307   {
308     if (map != null)
309     {
310
311       if (from <= to)
312       {
313         from = (map.getFromLowest() < from) ? from : map.getFromLowest();
314         to = (map.getFromHighest() > to) ? to : map.getFromHighest();
315         if (from > to)
316           return null;
317       }
318       else
319       {
320         from = (map.getFromHighest() > from) ? from : map.getFromHighest();
321         to = (map.getFromLowest() < to) ? to : map.getFromLowest();
322         if (from < to)
323           return null;
324       }
325       return map.locateInTo(from, to);
326     }
327     return new int[]
328     { from, to };
329   }
330
331   /**
332    * return a new mapping object with a maplist modifed to only map the visible
333    * regions defined by viscontigs.
334    * 
335    * @param viscontigs
336    * @return
337    */
338   public Mapping intersectVisContigs(int[] viscontigs)
339   {
340     Mapping copy = new Mapping(this);
341     if (map != null)
342     {
343       int vpos = 0;
344       int apos = 0;
345       Vector toRange = new Vector();
346       Vector fromRange = new Vector();
347       for (int vc = 0; vc < viscontigs.length; vc += 2)
348       {
349         // find a mapped range in this visible region
350         int[] mpr = locateMappedRange(1+viscontigs[vc], viscontigs[vc + 1]-1);
351         if (mpr != null)
352         {
353           for (int m = 0; m < mpr.length; m += 2)
354           {
355             toRange.addElement(new int[]
356             { mpr[m], mpr[m + 1] });
357             int[] xpos = locateRange(mpr[m], mpr[m + 1]);
358             for (int x = 0; x < xpos.length; x += 2)
359             {
360               fromRange.addElement(new int[]
361               { xpos[x], xpos[x + 1] });
362             }
363           }
364         }
365       }
366       int[] from = new int[fromRange.size()*2];
367       int[] to = new int[toRange.size()*2];
368       int[] r;
369       for (int f=0,fSize=fromRange.size(); f<fSize; f++)
370       {
371         r = (int[]) fromRange.elementAt(f);
372         from[f*2] = r[0];
373         from[f*2+1] = r[1];
374       }
375       for (int f=0,fSize=toRange.size(); f<fSize; f++)
376       {
377         r = (int[]) toRange.elementAt(f);
378         to[f*2] = r[0];
379         to[f*2+1] = r[1];
380       }
381       copy.setMap(new MapList(from, to, map.getFromRatio(), map.getToRatio()));
382     }
383     return copy;
384   }
385   public static void main(String[] args)
386   {
387     /**
388      * trite test of the intersectVisContigs method
389      * for a simple DNA -> Protein exon map and a range of visContigs
390      */
391     MapList fk = new MapList(new int[] { 1,6,8,13,15,23}, new int[] { 1,7}, 3, 1);
392     Mapping m = new Mapping(fk);
393     Mapping m_1 = m.intersectVisContigs(new int[] {fk.getFromLowest(), fk.getFromHighest()});
394     Mapping m_2 = m.intersectVisContigs(new int[] {1,7,11,20});
395     System.out.println(""+m_1.map.getFromRanges());
396     
397     
398   }
399   /**
400    * get the sequence being mapped to - if any
401    * @return null or a dataset sequence
402    */
403   public SequenceI getTo()
404   {
405     return to;
406   }
407   /**
408    * set the dataset sequence being mapped to if any
409    * @param tto
410    */
411   public void setTo(SequenceI tto)
412   {
413     to = tto;
414   }
415
416   /* (non-Javadoc)
417    * @see java.lang.Object#finalize()
418    */
419   protected void finalize() throws Throwable
420   {
421     map = null;
422     to = null;
423     super.finalize();
424   }
425   
426 }