08b1b52cea989eb33f4864469f4d7b9d3c9b70ae
[jalview.git] / src / jalview / io / vamsas / Rangetype.java
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.io.vamsas;
22
23 import jalview.io.VamsasAppDatastore;
24 import jalview.util.MessageManager;
25
26 import java.util.List;
27 import java.util.Vector;
28
29 import uk.ac.vamsas.client.Vobject;
30 import uk.ac.vamsas.objects.core.Local;
31 import uk.ac.vamsas.objects.core.MapType;
32 import uk.ac.vamsas.objects.core.Mapped;
33 import uk.ac.vamsas.objects.core.RangeType;
34 import uk.ac.vamsas.objects.core.Seg;
35
36 /**
37  * Enhances DatastoreItem objects with additional functions to do with RangeType
38  * objects
39  * 
40  * @author JimP
41  * 
42  */
43 public abstract class Rangetype extends DatastoreItem
44 {
45
46   public Rangetype()
47   {
48     super();
49   }
50
51   public Rangetype(VamsasAppDatastore datastore)
52   {
53     super(datastore);
54   }
55
56   public Rangetype(VamsasAppDatastore datastore, Vobject vobj, Class jvClass)
57   {
58     super(datastore, vobj, jvClass);
59   }
60
61   public Rangetype(VamsasAppDatastore datastore, Object jvobj, Class vClass)
62   {
63     super(datastore, jvobj, vClass);
64   }
65
66   /**
67    * get real bounds of a RangeType's specification. start and end are an
68    * inclusive range within which all segments and positions lie. TODO: refactor
69    * to vamsas utils
70    * 
71    * @param dseta
72    * @return int[] { start, end}
73    */
74   protected int[] getBounds(RangeType dseta)
75   {
76     if (dseta != null)
77     {
78       int[] se = null;
79       if (dseta.getSegCount() > 0 && dseta.getPosCount() > 0)
80       {
81         throw new Error(MessageManager.getString("error.invalid_vamsas_rangetype_cannot_resolve_lists"));
82       }
83       if (dseta.getSegCount() > 0)
84       {
85         se = getSegRange(dseta.getSeg(0), true);
86         for (int s = 1, sSize = dseta.getSegCount(); s < sSize; s++)
87         {
88           int nse[] = getSegRange(dseta.getSeg(s), true);
89           if (se[0] > nse[0])
90           {
91             se[0] = nse[0];
92           }
93           if (se[1] < nse[1])
94           {
95             se[1] = nse[1];
96           }
97         }
98       }
99       if (dseta.getPosCount() > 0)
100       {
101         // could do a polarity for pos range too. and pass back indication of
102         // discontinuities.
103         int pos = dseta.getPos(0).getI();
104         se = new int[]
105         { pos, pos };
106         for (int p = 0, pSize = dseta.getPosCount(); p < pSize; p++)
107         {
108           pos = dseta.getPos(p).getI();
109           if (se[0] > pos)
110           {
111             se[0] = pos;
112           }
113           if (se[1] < pos)
114           {
115             se[1] = pos;
116           }
117         }
118       }
119       return se;
120     }
121     return null;
122   }
123
124   /**
125    * map from a rangeType's internal frame to the referenced object's coordinate
126    * frame.
127    * 
128    * @param dseta
129    * @return int [] { ref(pos)...} for all pos in rangeType's frame.
130    */
131   protected int[] getMapping(RangeType dseta)
132   {
133     Vector posList = new Vector();
134     if (dseta != null)
135     {
136       int[] se = null;
137       if (dseta.getSegCount() > 0 && dseta.getPosCount() > 0)
138       {
139         throw new Error(MessageManager.getString("error.invalid_vamsas_rangetype_cannot_resolve_lists"));
140       }
141       if (dseta.getSegCount() > 0)
142       {
143         for (int s = 0, sSize = dseta.getSegCount(); s < sSize; s++)
144         {
145           se = getSegRange(dseta.getSeg(s), false);
146           int se_end = se[1 - se[2]] + (se[2] == 0 ? 1 : -1);
147           for (int p = se[se[2]]; p != se_end; p += se[2] == 0 ? 1 : -1)
148           {
149             posList.add(new Integer(p));
150           }
151         }
152       }
153       else if (dseta.getPosCount() > 0)
154       {
155         int pos = dseta.getPos(0).getI();
156
157         for (int p = 0, pSize = dseta.getPosCount(); p < pSize; p++)
158         {
159           pos = dseta.getPos(p).getI();
160           posList.add(new Integer(pos));
161         }
162       }
163     }
164     if (posList != null && posList.size() > 0)
165     {
166       int[] range = new int[posList.size()];
167       for (int i = 0; i < range.length; i++)
168       {
169         range[i] = ((Integer) posList.elementAt(i)).intValue();
170       }
171       posList.clear();
172       return range;
173     }
174     return null;
175   }
176
177   protected int[] getIntervals(RangeType range)
178   {
179     int[] intervals = null;
180     Vector posList = new Vector();
181     if (range != null)
182     {
183       int[] se = null;
184       if (range.getSegCount() > 0 && range.getPosCount() > 0)
185       {
186         throw new Error(MessageManager.getString("error.invalid_vamsas_rangetype_cannot_resolve_lists"));
187       }
188       if (range.getSegCount() > 0)
189       {
190         for (int s = 0, sSize = range.getSegCount(); s < sSize; s++)
191         {
192           se = getSegRange(range.getSeg(s), false);
193           posList.addElement(new Integer(se[0]));
194           posList.addElement(new Integer(se[1]));
195         }
196       }
197       else if (range.getPosCount() > 0)
198       {
199         int pos = range.getPos(0).getI();
200
201         for (int p = 0, pSize = range.getPosCount(); p < pSize; p++)
202         {
203           pos = range.getPos(p).getI();
204           posList.add(new Integer(pos));
205           posList.add(new Integer(pos));
206         }
207       }
208     }
209     if (posList != null && posList.size() > 0)
210     {
211       intervals = new int[posList.size()];
212       java.util.Enumeration e = posList.elements();
213       int i = 0;
214       while (e.hasMoreElements())
215       {
216         intervals[i++] = ((Integer) e.nextElement()).intValue();
217       }
218     }
219     return intervals;
220   }
221
222   /**
223    * initialise a range type object from a set of start/end inclusive intervals
224    * 
225    * @param mrt
226    * @param ranges
227    */
228   protected void initRangeType(RangeType mrt, List<int[]> ranges)
229   {
230     for (int[] range : ranges)
231     {
232       Seg vSeg = new Seg();
233       vSeg.setStart(range[0]);
234       vSeg.setEnd(range[1]);
235       vSeg.setInclusive(true);
236       mrt.addSeg(vSeg);
237     }
238   }
239
240   /**
241    * 
242    * @param maprange
243    *          where the from range is the local mapped range, and the to range
244    *          is the 'mapped' range in the MapRangeType
245    * @param default unit for local
246    * @param default unit for mapped
247    * @return MapList
248    */
249   protected jalview.util.MapList parsemapType(MapType maprange, int localu,
250           int mappedu)
251   {
252     jalview.util.MapList ml = null;
253     int[] localRange = getIntervals(maprange.getLocal());
254     int[] mappedRange = getIntervals(maprange.getMapped());
255     long lu = maprange.getLocal().hasUnit() ? maprange.getLocal().getUnit()
256             : localu;
257     long mu = maprange.getMapped().hasUnit() ? maprange.getMapped()
258             .getUnit() : mappedu;
259     ml = new jalview.util.MapList(localRange, mappedRange, (int) lu,
260             (int) mu);
261     return ml;
262   }
263
264   protected jalview.util.MapList parsemapType(MapType map)
265   {
266     if (!map.getLocal().hasUnit() || map.getMapped().hasUnit())
267     {
268       jalview.bin.Cache.log
269               .warn("using default mapping length of 1:1 for map "
270                       + (map.isRegistered() ? map.getVorbaId().toString()
271                               : ("<no Id registered> " + map.toString())));
272     }
273     return parsemapType(map, 1, 1);
274   }
275
276   /**
277    * initialise a MapType object from a MapList object.
278    * 
279    * @param maprange
280    * @param ml
281    * @param setUnits
282    */
283   protected void initMapType(MapType maprange, jalview.util.MapList ml,
284           boolean setUnits)
285   {
286     initMapType(maprange, ml, setUnits, false);
287   }
288
289   /**
290    * 
291    * @param maprange
292    * @param ml
293    * @param setUnits
294    * @param reverse
295    *          - reverse MapList mapping for Local and Mapped ranges and units
296    */
297   protected void initMapType(MapType maprange, jalview.util.MapList ml,
298           boolean setUnits, boolean reverse)
299   {
300     if (ml == null)
301     {
302       throw new Error(MessageManager.getString("error.implementation_error_maplist_is_null"));
303     }
304     maprange.setLocal(new Local());
305     maprange.setMapped(new Mapped());
306     if (!reverse)
307     {
308       initRangeType(maprange.getLocal(), ml.getFromRanges());
309       initRangeType(maprange.getMapped(), ml.getToRanges());
310     }
311     else
312     {
313       initRangeType(maprange.getLocal(), ml.getToRanges());
314       initRangeType(maprange.getMapped(), ml.getFromRanges());
315     }
316     if (setUnits)
317     {
318       if (!reverse)
319       {
320         maprange.getLocal().setUnit(ml.getFromRatio());
321         maprange.getMapped().setUnit(ml.getToRatio());
322       }
323       else
324       {
325         maprange.getLocal().setUnit(ml.getToRatio());
326         maprange.getMapped().setUnit(ml.getFromRatio());
327       }
328       // TODO: and verify - raise an implementation fault notice if local/mapped
329       // range % Local/Mapped Ratio != 0
330       // if (uk.ac.vamsas.objects.utils.Range.getIntervals(range))
331
332     }
333   }
334
335 }