update author list in license for (JAL-826)
[jalview.git] / src / jalview / io / vamsas / Rangetype.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.7)
3  * Copyright (C) 2011 J Procter, AM Waterhouse, J Engelhardt, LM Lui, G Barton, M Clamp, S Searle
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 of the License, or (at your option) any later version.
10  * 
11  * Jalview is distributed in the hope that it will be useful, but 
12  * WITHOUT ANY WARRANTY; without even the implied warranty 
13  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
14  * PURPOSE.  See the GNU General Public License for more details.
15  * 
16  * You should have received a copy of the GNU General Public License along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 package jalview.io.vamsas;
19
20 import java.util.Vector;
21
22 import uk.ac.vamsas.client.Vobject;
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.DBRefEntry;
30 import jalview.datamodel.Mapping;
31 import jalview.io.VamsasAppDatastore;
32
33 /**
34  * Enhances DatastoreItem objects with additional functions to do with RangeType
35  * objects
36  * 
37  * @author JimP
38  * 
39  */
40 public abstract class Rangetype extends DatastoreItem
41 {
42
43   public Rangetype()
44   {
45     super();
46   }
47
48   public Rangetype(VamsasAppDatastore datastore)
49   {
50     super(datastore);
51   }
52
53   public Rangetype(VamsasAppDatastore datastore, Vobject vobj, Class jvClass)
54   {
55     super(datastore, vobj, jvClass);
56   }
57
58   public Rangetype(VamsasAppDatastore datastore, Object jvobj, Class vClass)
59   {
60     super(datastore, jvobj, vClass);
61   }
62
63   /**
64    * get real bounds of a RangeType's specification. start and end are an
65    * inclusive range within which all segments and positions lie. TODO: refactor
66    * to vamsas utils
67    * 
68    * @param dseta
69    * @return int[] { start, end}
70    */
71   protected int[] getBounds(RangeType dseta)
72   {
73     if (dseta != null)
74     {
75       int[] se = null;
76       if (dseta.getSegCount() > 0 && dseta.getPosCount() > 0)
77       {
78         throw new Error(
79                 "Invalid vamsas RangeType - cannot resolve both lists of Pos and Seg from choice!");
80       }
81       if (dseta.getSegCount() > 0)
82       {
83         se = getSegRange(dseta.getSeg(0), true);
84         for (int s = 1, sSize = dseta.getSegCount(); s < sSize; s++)
85         {
86           int nse[] = getSegRange(dseta.getSeg(s), true);
87           if (se[0] > nse[0])
88           {
89             se[0] = nse[0];
90           }
91           if (se[1] < nse[1])
92           {
93             se[1] = nse[1];
94           }
95         }
96       }
97       if (dseta.getPosCount() > 0)
98       {
99         // could do a polarity for pos range too. and pass back indication of
100         // discontinuities.
101         int pos = dseta.getPos(0).getI();
102         se = new int[]
103         { pos, pos };
104         for (int p = 0, pSize = dseta.getPosCount(); p < pSize; p++)
105         {
106           pos = dseta.getPos(p).getI();
107           if (se[0] > pos)
108           {
109             se[0] = pos;
110           }
111           if (se[1] < pos)
112           {
113             se[1] = pos;
114           }
115         }
116       }
117       return se;
118     }
119     return null;
120   }
121
122   /**
123    * map from a rangeType's internal frame to the referenced object's coordinate
124    * frame.
125    * 
126    * @param dseta
127    * @return int [] { ref(pos)...} for all pos in rangeType's frame.
128    */
129   protected int[] getMapping(RangeType dseta)
130   {
131     Vector posList = new Vector();
132     if (dseta != null)
133     {
134       int[] se = null;
135       if (dseta.getSegCount() > 0 && dseta.getPosCount() > 0)
136       {
137         throw new Error(
138                 "Invalid vamsas RangeType - cannot resolve both lists of Pos and Seg from choice!");
139       }
140       if (dseta.getSegCount() > 0)
141       {
142         for (int s = 0, sSize = dseta.getSegCount(); s < sSize; s++)
143         {
144           se = getSegRange(dseta.getSeg(s), false);
145           int se_end = se[1 - se[2]] + (se[2] == 0 ? 1 : -1);
146           for (int p = se[se[2]]; p != se_end; p += se[2] == 0 ? 1 : -1)
147           {
148             posList.add(new Integer(p));
149           }
150         }
151       }
152       else if (dseta.getPosCount() > 0)
153       {
154         int pos = dseta.getPos(0).getI();
155
156         for (int p = 0, pSize = dseta.getPosCount(); p < pSize; p++)
157         {
158           pos = dseta.getPos(p).getI();
159           posList.add(new Integer(pos));
160         }
161       }
162     }
163     if (posList != null && posList.size() > 0)
164     {
165       int[] range = new int[posList.size()];
166       for (int i = 0; i < range.length; i++)
167       {
168         range[i] = ((Integer) posList.elementAt(i)).intValue();
169       }
170       posList.clear();
171       return range;
172     }
173     return null;
174   }
175
176   protected int[] getIntervals(RangeType range)
177   {
178     int[] intervals = null;
179     Vector posList = new Vector();
180     if (range != null)
181     {
182       int[] se = null;
183       if (range.getSegCount() > 0 && range.getPosCount() > 0)
184       {
185         throw new Error(
186                 "Invalid vamsas RangeType - cannot resolve both lists of Pos and Seg from choice!");
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 range
227    */
228   protected void initRangeType(RangeType mrt, int[] range)
229   {
230     for (int i = 0; i < range.length; i += 2)
231     {
232       Seg vSeg = new Seg();
233       vSeg.setStart(range[i]);
234       vSeg.setEnd(range[i + 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(
303               "Implementation error. MapList is null for initMapType.");
304     }
305     maprange.setLocal(new Local());
306     maprange.setMapped(new Mapped());
307     if (!reverse)
308     {
309       initRangeType(maprange.getLocal(), ml.getFromRanges());
310       initRangeType(maprange.getMapped(), ml.getToRanges());
311     }
312     else
313     {
314       initRangeType(maprange.getLocal(), ml.getToRanges());
315       initRangeType(maprange.getMapped(), ml.getFromRanges());
316     }
317     if (setUnits)
318     {
319       if (!reverse)
320       {
321         maprange.getLocal().setUnit(ml.getFromRatio());
322         maprange.getMapped().setUnit(ml.getToRatio());
323       }
324       else
325       {
326         maprange.getLocal().setUnit(ml.getToRatio());
327         maprange.getMapped().setUnit(ml.getFromRatio());
328       }
329       // TODO: and verify - raise an implementation fault notice if local/mapped
330       // range % Local/Mapped Ratio != 0
331       // if (uk.ac.vamsas.objects.utils.Range.getIntervals(range))
332
333     }
334   }
335
336 }