debugged mappings and translated sequence recovery
[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         SequenceFeature[] vf = new SequenceFeature[frange.length / 2];
223         for (int i = 0, v = 0; i < frange.length; i += 2, v++)
224         {
225           vf[v] = new SequenceFeature(f);
226           vf[v].setBegin(frange[i]);
227           vf[v].setEnd(frange[i + 1]);
228           if (frange.length > 2)
229             vf[v].setDescription(f.getDescription() + "\nPart " + v);
230         }
231         return vf;
232       }
233     }
234     if (false) // else
235     {
236       int[] word = getWord(f.getBegin());
237       if (word[0] < word[1])
238       {
239         f.setBegin(word[0]);
240       }
241       else
242       {
243         f.setBegin(word[1]);
244       }
245       word = getWord(f.getEnd());
246       if (word[0] > word[1])
247       {
248         f.setEnd(word[0]);
249       }
250       else
251       {
252         f.setEnd(word[1]);
253       }
254     }
255     // give up and just return the feature.
256     return new SequenceFeature[]
257     { f };
258   }
259
260   /**
261    * return a series of contigs on the associated sequence corresponding to the
262    * from,to interval on the mapped reference frame
263    * 
264    * @param from
265    * @param to
266    * @return int[] { from_i, to_i for i=1 to n contiguous regions in the
267    *         associated sequence}
268    */
269   public int[] locateRange(int from, int to)
270   {
271     if (map != null)
272     {
273       if (from <= to)
274       {
275         from = (map.getToLowest() < from) ? from : map.getToLowest();
276         to = (map.getToHighest() > to) ? to : map.getToHighest();
277         if (from > to)
278           return null;
279       }
280       else
281       {
282         from = (map.getToHighest() > from) ? from : map.getToHighest();
283         to = (map.getToLowest() < to) ? to : map.getToLowest();
284         if (from < to)
285           return null;
286       }
287       return map.locateInFrom(from, to);
288     }
289     return new int[]
290     { from, to };
291   }
292
293   /**
294    * return a series of mapped contigs mapped from a range on the associated
295    * sequence
296    * 
297    * @param from
298    * @param to
299    * @return
300    */
301   public int[] locateMappedRange(int from, int to)
302   {
303     if (map != null)
304     {
305
306       if (from <= to)
307       {
308         from = (map.getFromLowest() < from) ? from : map.getFromLowest();
309         to = (map.getFromHighest() > to) ? to : map.getFromHighest();
310         if (from > to)
311           return null;
312       }
313       else
314       {
315         from = (map.getFromHighest() > from) ? from : map.getFromHighest();
316         to = (map.getFromLowest() < to) ? to : map.getFromLowest();
317         if (from < to)
318           return null;
319       }
320       return map.locateInTo(from, to);
321     }
322     return new int[]
323     { from, to };
324   }
325
326   /**
327    * return a new mapping object with a maplist modifed to only map the visible
328    * regions defined by viscontigs.
329    * 
330    * @param viscontigs
331    * @return
332    */
333   public Mapping intersectVisContigs(int[] viscontigs)
334   {
335     Mapping copy = new Mapping(this);
336     if (map != null)
337     {
338       int vpos = 0;
339       int apos = 0;
340       Vector toRange = new Vector();
341       Vector fromRange = new Vector();
342       for (int vc = 0; vc < viscontigs.length; vc += 2)
343       {
344         // find a mapped range in this visible region
345         int[] mpr = locateMappedRange(1+viscontigs[vc], viscontigs[vc + 1]-1);
346         if (mpr != null)
347         {
348           for (int m = 0; m < mpr.length; m += 2)
349           {
350             toRange.addElement(new int[]
351             { mpr[m], mpr[m + 1] });
352             int[] xpos = locateRange(mpr[m], mpr[m + 1]);
353             for (int x = 0; x < xpos.length; x += 2)
354             {
355               fromRange.addElement(new int[]
356               { xpos[x], xpos[x + 1] });
357             }
358           }
359         }
360       }
361       int[] from = new int[fromRange.size()*2];
362       int[] to = new int[toRange.size()*2];
363       int[] r;
364       for (int f=0,fSize=fromRange.size(); f<fSize; f++)
365       {
366         r = (int[]) fromRange.elementAt(f);
367         from[f*2] = r[0];
368         from[f*2+1] = r[1];
369       }
370       for (int f=0,fSize=toRange.size(); f<fSize; f++)
371       {
372         r = (int[]) toRange.elementAt(f);
373         to[f*2] = r[0];
374         to[f*2+1] = r[1];
375       }
376       copy.setMap(new MapList(from, to, map.getFromRatio(), map.getToRatio()));
377     }
378     return copy;
379   }
380   public static void main(String[] args)
381   {
382     /**
383      * trite test of the intersectVisContigs method
384      * for a simple DNA -> Protein exon map and a range of visContigs
385      */
386     MapList fk = new MapList(new int[] { 1,6,8,13,15,23}, new int[] { 1,7}, 3, 1);
387     Mapping m = new Mapping(fk);
388     Mapping m_1 = m.intersectVisContigs(new int[] {fk.getFromLowest(), fk.getFromHighest()});
389     Mapping m_2 = m.intersectVisContigs(new int[] {1,7,11,20});
390     System.out.println(""+m_1.map.getFromRanges());
391     
392     
393   }
394   /**
395    * get the sequence being mapped to - if any
396    * @return null or a dataset sequence
397    */
398   public SequenceI getTo()
399   {
400     return to;
401   }
402   /**
403    * set the dataset sequence being mapped to if any
404    * @param tto
405    */
406   public void setTo(SequenceI tto)
407   {
408     to = tto;
409   }
410
411   /* (non-Javadoc)
412    * @see java.lang.Object#finalize()
413    */
414   protected void finalize() throws Throwable
415   {
416     map = null;
417     to = null;
418     super.finalize();
419   }
420   
421 }