merge from 2_4_Release branch
[jalview.git] / src / jalview / io / vamsas / Rangetype.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.4)
3  * Copyright (C) 2008 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
4  * 
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  * 
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  * 
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
18  */
19 package jalview.io.vamsas;
20
21 import java.util.Vector;
22
23 import uk.ac.vamsas.objects.core.Local;
24 import uk.ac.vamsas.objects.core.Map;
25 import uk.ac.vamsas.objects.core.MapType;
26 import uk.ac.vamsas.objects.core.Mapped;
27 import uk.ac.vamsas.objects.core.RangeType;
28 import uk.ac.vamsas.objects.core.Seg;
29 import jalview.datamodel.Mapping;
30 import jalview.io.VamsasAppDatastore;
31
32 public class Rangetype extends DatastoreItem
33 {
34
35   public Rangetype()
36   {
37     super();
38   }
39
40   public Rangetype(VamsasAppDatastore datastore)
41   {
42     super(datastore);
43   }
44
45   /**
46    * get real bounds of a RangeType's specification. start and end are an
47    * inclusive range within which all segments and positions lie. TODO: refactor
48    * to vamsas utils
49    * 
50    * @param dseta
51    * @return int[] { start, end}
52    */
53   protected int[] getBounds(RangeType dseta)
54   {
55     if (dseta != null)
56     {
57       int[] se = null;
58       if (dseta.getSegCount() > 0 && dseta.getPosCount() > 0)
59       {
60         throw new Error(
61                 "Invalid vamsas RangeType - cannot resolve both lists of Pos and Seg from choice!");
62       }
63       if (dseta.getSegCount() > 0)
64       {
65         se = getSegRange(dseta.getSeg(0), true);
66         for (int s = 1, sSize = dseta.getSegCount(); s < sSize; s++)
67         {
68           int nse[] = getSegRange(dseta.getSeg(s), true);
69           if (se[0] > nse[0])
70           {
71             se[0] = nse[0];
72           }
73           if (se[1] < nse[1])
74           {
75             se[1] = nse[1];
76           }
77         }
78       }
79       if (dseta.getPosCount() > 0)
80       {
81         // could do a polarity for pos range too. and pass back indication of
82         // discontinuities.
83         int pos = dseta.getPos(0).getI();
84         se = new int[]
85         { pos, pos };
86         for (int p = 0, pSize = dseta.getPosCount(); p < pSize; p++)
87         {
88           pos = dseta.getPos(p).getI();
89           if (se[0] > pos)
90           {
91             se[0] = pos;
92           }
93           if (se[1] < pos)
94           {
95             se[1] = pos;
96           }
97         }
98       }
99       return se;
100     }
101     return null;
102   }
103
104   /**
105    * map from a rangeType's internal frame to the referenced object's coordinate
106    * frame.
107    * 
108    * @param dseta
109    * @return int [] { ref(pos)...} for all pos in rangeType's frame.
110    */
111   protected int[] getMapping(RangeType dseta)
112   {
113     Vector posList = new Vector();
114     if (dseta != null)
115     {
116       int[] se = null;
117       if (dseta.getSegCount() > 0 && dseta.getPosCount() > 0)
118       {
119         throw new Error(
120                 "Invalid vamsas RangeType - cannot resolve both lists of Pos and Seg from choice!");
121       }
122       if (dseta.getSegCount() > 0)
123       {
124         for (int s = 0, sSize = dseta.getSegCount(); s < sSize; s++)
125         {
126           se = getSegRange(dseta.getSeg(s), false);
127           int se_end = se[1 - se[2]] + (se[2] == 0 ? 1 : -1);
128           for (int p = se[se[2]]; p != se_end; p += se[2] == 0 ? 1 : -1)
129           {
130             posList.add(new Integer(p));
131           }
132         }
133       }
134       else if (dseta.getPosCount() > 0)
135       {
136         int pos = dseta.getPos(0).getI();
137
138         for (int p = 0, pSize = dseta.getPosCount(); p < pSize; p++)
139         {
140           pos = dseta.getPos(p).getI();
141           posList.add(new Integer(pos));
142         }
143       }
144     }
145     if (posList != null && posList.size() > 0)
146     {
147       int[] range = new int[posList.size()];
148       for (int i = 0; i < range.length; i++)
149       {
150         range[i] = ((Integer) posList.elementAt(i)).intValue();
151       }
152       posList.clear();
153       return range;
154     }
155     return null;
156   }
157
158   protected int[] getIntervals(RangeType range)
159   {
160     int[] intervals = null;
161     Vector posList = new Vector();
162     if (range != null)
163     {
164       int[] se = null;
165       if (range.getSegCount() > 0 && range.getPosCount() > 0)
166       {
167         throw new Error(
168                 "Invalid vamsas RangeType - cannot resolve both lists of Pos and Seg from choice!");
169       }
170       if (range.getSegCount() > 0)
171       {
172         for (int s = 0, sSize = range.getSegCount(); s < sSize; s++)
173         {
174           se = getSegRange(range.getSeg(s), false);
175           posList.addElement(new Integer(se[0]));
176           posList.addElement(new Integer(se[1]));
177         }
178       }
179       else if (range.getPosCount() > 0)
180       {
181         int pos = range.getPos(0).getI();
182
183         for (int p = 0, pSize = range.getPosCount(); p < pSize; p++)
184         {
185           pos = range.getPos(p).getI();
186           posList.add(new Integer(pos));
187           posList.add(new Integer(pos));
188         }
189       }
190     }
191     if (posList != null && posList.size() > 0)
192     {
193       intervals = new int[posList.size()];
194       java.util.Enumeration e = posList.elements();
195       int i = 0;
196       while (e.hasMoreElements())
197       {
198         intervals[i++] = ((Integer) e.nextElement()).intValue();
199       }
200     }
201     return intervals;
202   }
203
204   /**
205    * initialise a range type object from a set of start/end inclusive intervals
206    * 
207    * @param mrt
208    * @param range
209    */
210   protected void initRangeType(RangeType mrt, int[] range)
211   {
212     for (int i = 0; i < range.length; i += 2)
213     {
214       Seg vSeg = new Seg();
215       vSeg.setStart(range[i]);
216       vSeg.setEnd(range[i + 1]);
217       vSeg.setInclusive(true);
218       mrt.addSeg(vSeg);
219     }
220   }
221
222   /**
223    * 
224    * @param maprange
225    *                where the from range is the local mapped range, and the to
226    *                range is the 'mapped' range in the MapRangeType
227    * @param default
228    *                unit for local
229    * @param default
230    *                unit for mapped
231    * @return MapList
232    */
233   protected jalview.util.MapList parsemapType(MapType maprange, int localu,
234           int mappedu)
235   {
236     jalview.util.MapList ml = null;
237     int[] localRange = getIntervals(maprange.getLocal());
238     int[] mappedRange = getIntervals(maprange.getMapped());
239     long lu = maprange.getLocal().hasUnit() ? maprange.getLocal().getUnit()
240             : localu;
241     long mu = maprange.getMapped().hasUnit() ? maprange.getMapped()
242             .getUnit() : mappedu;
243     ml = new jalview.util.MapList(localRange, mappedRange, (int) lu,
244             (int) mu);
245     return ml;
246   }
247
248   protected jalview.util.MapList parsemapType(MapType map)
249   {
250     if (!map.getLocal().hasUnit() || map.getMapped().hasUnit())
251     {
252       jalview.bin.Cache.log
253               .warn("using default mapping length of 1:1 for map "
254                       + (map.isRegistered() ? map.getVorbaId().toString()
255                               : ("<no Id registered> " + map.toString())));
256     }
257     return parsemapType(map, 1, 1);
258   }
259
260   /**
261    * initialise a MapType object from a MapList object.
262    * 
263    * @param maprange
264    * @param ml
265    * @param setUnits
266    */
267   protected void initMapType(MapType maprange, jalview.util.MapList ml,
268           boolean setUnits)
269   {
270     initMapType(maprange, ml, setUnits, false);
271   }
272
273   /**
274    * 
275    * @param maprange
276    * @param ml
277    * @param setUnits
278    * @param reverse -
279    *                reverse MapList mapping for Local and Mapped ranges and
280    *                units
281    */
282   protected void initMapType(MapType maprange, jalview.util.MapList ml,
283           boolean setUnits, boolean reverse)
284   {
285     if (ml == null)
286     {
287       throw new Error(
288               "Implementation error. MapList is null for initMapType.");
289     }
290     maprange.setLocal(new Local());
291     maprange.setMapped(new Mapped());
292     if (!reverse)
293     {
294       initRangeType(maprange.getLocal(), ml.getFromRanges());
295       initRangeType(maprange.getMapped(), ml.getToRanges());
296     }
297     else
298     {
299       initRangeType(maprange.getLocal(), ml.getToRanges());
300       initRangeType(maprange.getMapped(), ml.getFromRanges());
301     }
302     if (setUnits)
303     {
304       if (!reverse)
305       {
306         maprange.getLocal().setUnit(ml.getFromRatio());
307         maprange.getMapped().setUnit(ml.getToRatio());
308       }
309       else
310       {
311         maprange.getLocal().setUnit(ml.getToRatio());
312         maprange.getMapped().setUnit(ml.getFromRatio());
313       }
314     }
315   }
316
317 }