a542b5ddf7a0697cc3bed4ca35b44c6098cdb5f1
[jalview.git] / src / jalview / io / vamsas / Rangetype.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8)
3  * Copyright (C) 2012 J Procter, AM Waterhouse, LM Lui, J Engelhardt, 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.MapType;
25 import uk.ac.vamsas.objects.core.Mapped;
26 import uk.ac.vamsas.objects.core.RangeType;
27 import uk.ac.vamsas.objects.core.Seg;
28 import jalview.io.VamsasAppDatastore;
29
30 /**
31  * Enhances DatastoreItem objects with additional functions to do with RangeType
32  * objects
33  * 
34  * @author JimP
35  * 
36  */
37 public abstract class Rangetype extends DatastoreItem
38 {
39
40   public Rangetype()
41   {
42     super();
43   }
44
45   public Rangetype(VamsasAppDatastore datastore)
46   {
47     super(datastore);
48   }
49
50   public Rangetype(VamsasAppDatastore datastore, Vobject vobj, Class jvClass)
51   {
52     super(datastore, vobj, jvClass);
53   }
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 range
241    *          is the 'mapped' range in the MapRangeType
242    * @param default unit for local
243    * @param default unit for mapped
244    * @return MapList
245    */
246   protected jalview.util.MapList parsemapType(MapType maprange, int localu,
247           int mappedu)
248   {
249     jalview.util.MapList ml = null;
250     int[] localRange = getIntervals(maprange.getLocal());
251     int[] mappedRange = getIntervals(maprange.getMapped());
252     long lu = maprange.getLocal().hasUnit() ? maprange.getLocal().getUnit()
253             : localu;
254     long mu = maprange.getMapped().hasUnit() ? maprange.getMapped()
255             .getUnit() : mappedu;
256     ml = new jalview.util.MapList(localRange, mappedRange, (int) lu,
257             (int) mu);
258     return ml;
259   }
260
261   protected jalview.util.MapList parsemapType(MapType map)
262   {
263     if (!map.getLocal().hasUnit() || map.getMapped().hasUnit())
264     {
265       jalview.bin.Cache.log
266               .warn("using default mapping length of 1:1 for map "
267                       + (map.isRegistered() ? map.getVorbaId().toString()
268                               : ("<no Id registered> " + map.toString())));
269     }
270     return parsemapType(map, 1, 1);
271   }
272
273   /**
274    * initialise a MapType object from a MapList object.
275    * 
276    * @param maprange
277    * @param ml
278    * @param setUnits
279    */
280   protected void initMapType(MapType maprange, jalview.util.MapList ml,
281           boolean setUnits)
282   {
283     initMapType(maprange, ml, setUnits, false);
284   }
285
286   /**
287    * 
288    * @param maprange
289    * @param ml
290    * @param setUnits
291    * @param reverse
292    *          - reverse MapList mapping for Local and Mapped ranges and units
293    */
294   protected void initMapType(MapType maprange, jalview.util.MapList ml,
295           boolean setUnits, boolean reverse)
296   {
297     if (ml == null)
298     {
299       throw new Error(
300               "Implementation error. MapList is null for initMapType.");
301     }
302     maprange.setLocal(new Local());
303     maprange.setMapped(new Mapped());
304     if (!reverse)
305     {
306       initRangeType(maprange.getLocal(), ml.getFromRanges());
307       initRangeType(maprange.getMapped(), ml.getToRanges());
308     }
309     else
310     {
311       initRangeType(maprange.getLocal(), ml.getToRanges());
312       initRangeType(maprange.getMapped(), ml.getFromRanges());
313     }
314     if (setUnits)
315     {
316       if (!reverse)
317       {
318         maprange.getLocal().setUnit(ml.getFromRatio());
319         maprange.getMapped().setUnit(ml.getToRatio());
320       }
321       else
322       {
323         maprange.getLocal().setUnit(ml.getToRatio());
324         maprange.getMapped().setUnit(ml.getFromRatio());
325       }
326       // TODO: and verify - raise an implementation fault notice if local/mapped
327       // range % Local/Mapped Ratio != 0
328       // if (uk.ac.vamsas.objects.utils.Range.getIntervals(range))
329
330     }
331   }
332
333 }