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