debug message for default mapping
[vamsas.git] / src / uk / ac / vamsas / objects / utils / Range.java
1 package uk.ac.vamsas.objects.utils;\r
2 \r
3 import java.util.Vector;\r
4 \r
5 import uk.ac.vamsas.objects.core.Local;\r
6 import uk.ac.vamsas.objects.core.MapType;\r
7 import uk.ac.vamsas.objects.core.Mapped;\r
8 import uk.ac.vamsas.objects.core.RangeType;\r
9 import uk.ac.vamsas.objects.core.Seg;\r
10 \r
11 /**\r
12  * Utilities for working with RangeType and MapType objects.\r
13  * Derived from bitter experience.\r
14  * @author JimP\r
15  *\r
16  */\r
17 public class Range {\r
18   static org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getFactory().getLog(Range.class);\r
19 \r
20   /**\r
21    * get start<end range of segment, adjusting for inclusivity flag and\r
22    * polarity.\r
23    *\r
24    * @param visSeg\r
25    * @param ensureDirection when true - always ensure start is less than end.\r
26    * @return int[] { start, end, direction} where direction==1 for range running from end to start.\r
27    */\r
28   public static int[] getSegRange(Seg visSeg, boolean ensureDirection)\r
29   {\r
30     boolean incl = visSeg.getInclusive();\r
31     // adjust for inclusive flag.\r
32     int pol = (visSeg.getStart() <= visSeg.getEnd()) ? 1 : -1; // polarity of\r
33     // region.\r
34     int start = visSeg.getStart() + (incl ? 0 : pol);\r
35     int end = visSeg.getEnd() + (incl ? 0 : -pol);\r
36     if (ensureDirection && pol == -1)\r
37     {\r
38       // jalview doesn't deal with inverted ranges, yet.\r
39       int t = end;\r
40       end = start;\r
41       start = t;\r
42     }\r
43     return new int[]\r
44         {\r
45         start, end, pol < 0 ? 1 : 0};\r
46   }\r
47 \r
48   /**\r
49    * get real bounds of a RangeType's specification. start and end are an\r
50    * inclusive range within which all segments and positions lie.\r
51    * TODO: refactor to vamsas utils\r
52    * @param dseta\r
53    * @return int[] { start, end}\r
54    */\r
55   public static int[] getBounds(RangeType dseta)\r
56   {\r
57     if (dseta != null)\r
58     {\r
59       int[] se = null;\r
60       if (dseta.getSegCount() > 0 && dseta.getPosCount() > 0)\r
61       {\r
62         throw new Error("Invalid vamsas RangeType - cannot resolve both lists of Pos and Seg from choice!");\r
63       }\r
64       if (dseta.getSegCount() > 0)\r
65       {\r
66         se = getSegRange(dseta.getSeg(0), true);\r
67         for (int s = 1, sSize = dseta.getSegCount(); s < sSize; s++)\r
68         {\r
69           int nse[] = getSegRange(dseta.getSeg(s), true);\r
70           if (se[0] > nse[0])\r
71           {\r
72             se[0] = nse[0];\r
73           }\r
74           if (se[1] < nse[1])\r
75           {\r
76             se[1] = nse[1];\r
77           }\r
78         }\r
79       }\r
80       if (dseta.getPosCount() > 0)\r
81       {\r
82         // could do a polarity for pos range too. and pass back indication of discontinuities.\r
83         int pos = dseta.getPos(0).getI();\r
84         se = new int[]\r
85             {\r
86             pos, pos};\r
87         for (int p = 0, pSize = dseta.getPosCount(); p < pSize; p++)\r
88         {\r
89           pos = dseta.getPos(p).getI();\r
90           if (se[0] > pos)\r
91           {\r
92             se[0] = pos;\r
93           }\r
94           if (se[1] < pos)\r
95           {\r
96             se[1] = pos;\r
97           }\r
98         }\r
99       }\r
100       return se;\r
101     }\r
102     return null;\r
103   }\r
104 \r
105   /**\r
106    * map from a rangeType's internal frame to the referenced object's coordinate frame.\r
107    * @param dseta\r
108    * @return int [] { ref(pos)...} for all pos in rangeType's frame.\r
109    */\r
110   public static int[] getMapping(RangeType dseta)\r
111   {\r
112     Vector posList = new Vector();\r
113     if (dseta != null)\r
114     {\r
115       int[] se = null;\r
116       if (dseta.getSegCount() > 0 && dseta.getPosCount() > 0)\r
117       {\r
118         throw new Error("Invalid vamsas RangeType - cannot resolve both lists of Pos and Seg from choice!");\r
119       }\r
120       if (dseta.getSegCount() > 0)\r
121       {\r
122         for (int s = 0, sSize = dseta.getSegCount(); s < sSize; s++)\r
123         {\r
124           se = getSegRange(dseta.getSeg(s), false);\r
125           int se_end = se[1 - se[2]] + (se[2] == 0 ? 1 : -1);\r
126           for (int p = se[se[2]]; p != se_end; p += se[2] == 0 ? 1 : -1)\r
127           {\r
128             posList.add(new Integer(p));\r
129           }\r
130         }\r
131       }\r
132       else if (dseta.getPosCount() > 0)\r
133       {\r
134         int pos = dseta.getPos(0).getI();\r
135 \r
136         for (int p = 0, pSize = dseta.getPosCount(); p < pSize; p++)\r
137         {\r
138           pos = dseta.getPos(p).getI();\r
139           posList.add(new Integer(pos));\r
140         }\r
141       }\r
142     }\r
143     if (posList != null && posList.size() > 0)\r
144     {\r
145       int[] range = new int[posList.size()];\r
146       for (int i = 0; i < range.length; i++)\r
147       {\r
148         range[i] = ( (Integer) posList.elementAt(i)).intValue();\r
149       }\r
150       posList.clear();\r
151       return range;\r
152     }\r
153     return null;\r
154   }\r
155 \r
156   public static int[] getIntervals(RangeType range)\r
157   {\r
158     int[] intervals=null;\r
159     Vector posList = new Vector();\r
160     if (range != null)\r
161     {\r
162       int[] se = null;\r
163       if (range.getSegCount() > 0 && range.getPosCount() > 0)\r
164       {\r
165         throw new Error("Invalid vamsas RangeType - cannot resolve both lists of Pos and Seg from choice!");\r
166 }\r
167       if (range.getSegCount() > 0)\r
168       {\r
169         for (int s = 0, sSize = range.getSegCount(); s < sSize; s++)\r
170         {\r
171           se = getSegRange(range.getSeg(s), false);\r
172           posList.addElement(new Integer(se[0]));\r
173           posList.addElement(new Integer(se[1]));\r
174         }\r
175       }\r
176       else if (range.getPosCount() > 0)\r
177       {\r
178         int pos = range.getPos(0).getI();\r
179         for (int p = 0, pSize = range.getPosCount(); p < pSize; p++)\r
180         {\r
181           pos = range.getPos(p).getI();\r
182           posList.add(new Integer(pos));\r
183           posList.add(new Integer(pos));\r
184         }\r
185       }\r
186     }\r
187     if (posList != null && posList.size() > 0)\r
188     {\r
189       intervals=new int[posList.size()];\r
190       java.util.Enumeration e = posList.elements();\r
191       int i=0;\r
192       while (e.hasMoreElements())\r
193       {\r
194         intervals[i++] = ((Integer)e.nextElement()).intValue();\r
195       }\r
196     }\r
197     return intervals;\r
198   }\r
199   /**\r
200    * initialise a range type object from a set of start/end inclusive intervals\r
201    * @param mrt\r
202    * @param range\r
203    */\r
204   public static void initRangeType(RangeType mrt, int[] range)\r
205   {\r
206     for (int i=0; i<range.length; i+=2)\r
207     {\r
208       Seg vSeg = new Seg();\r
209       vSeg.setStart(range[i]);\r
210       vSeg.setEnd(range[i+1]);\r
211       vSeg.setInclusive(true);\r
212       mrt.addSeg(vSeg);\r
213     }\r
214   }\r
215 \r
216   /**\r
217    * \r
218    * @param maprange where the from range is the local mapped range, and the to range is the 'mapped' range in the MapRangeType\r
219    * @param default unit for local\r
220    * @param default unit for mapped\r
221    * @return MapList\r
222    */\r
223   public static MapList parsemapType(MapType maprange, int localu, int mappedu)\r
224   {\r
225     MapList ml = null;\r
226     int[] localRange = getIntervals(maprange.getLocal());\r
227     int[] mappedRange = getIntervals(maprange.getMapped());\r
228     long lu = maprange.getLocal().hasUnit() ? maprange.getLocal().getUnit() : localu;\r
229     long mu = maprange.getMapped().hasUnit() ? maprange.getMapped().getUnit() : mappedu;\r
230     ml = new MapList(localRange, mappedRange, (int)lu, (int)mu);\r
231     return ml;\r
232   }\r
233   /**\r
234    * Parse map with default units of 1,1\r
235    * @param map\r
236    * @return MapList representing map\r
237    */\r
238   public static MapList parsemapType(MapType map)\r
239   {\r
240     if (!map.getLocal().hasUnit() || map.getMapped().hasUnit())\r
241     {\r
242       if (log.isDebugEnabled())\r
243       { \r
244         log.debug(\r
245                 "using default mapping length of 1:1 for map "\r
246               +(map.isRegistered() ? map.getVorbaId().toString() : ("<no Id registered> "+map.toString())));\r
247       }\r
248     }\r
249     return parsemapType(map, 1, 1); \r
250   }\r
251 \r
252   /**\r
253    * initialise a MapType object from a MapList object.\r
254    * @param maprange\r
255    * @param ml\r
256    * @param setUnits\r
257    */\r
258   public static void initMapType(MapType maprange, MapList ml, boolean setUnits)\r
259   {\r
260     initMapType(maprange, ml, setUnits, false);\r
261   }\r
262   /**\r
263    * \r
264    * @param maprange\r
265    * @param ml\r
266    * @param setUnits\r
267    * @param reverse - reverse MapList mapping for Local and Mapped ranges and units \r
268    */\r
269   public static void initMapType(MapType maprange, MapList ml, boolean setUnits, boolean reverse)\r
270   {\r
271     maprange.setLocal(new Local());\r
272     maprange.setMapped(new Mapped());\r
273     if (!reverse)\r
274       {\r
275       initRangeType(maprange.getLocal(), ml.getFromRanges());\r
276       initRangeType(maprange.getMapped(), ml.getToRanges());\r
277       } else {\r
278         initRangeType(maprange.getLocal(), ml.getToRanges());\r
279         initRangeType(maprange.getMapped(), ml.getFromRanges());\r
280       }\r
281     if (setUnits)\r
282     {\r
283       if (!reverse)\r
284       { \r
285         maprange.getLocal().setUnit(ml.getFromRatio());\r
286         maprange.getMapped().setUnit(ml.getToRatio());\r
287       } else {\r
288         maprange.getLocal().setUnit(ml.getToRatio());\r
289         maprange.getMapped().setUnit(ml.getFromRatio());\r
290       }\r
291     }\r
292   }\r
293 \r
294 }