3cc977fd745fcd73f32bcfc81b86f34e9e8935e2
[jalview.git] / src / jalview / io / vamsas / Rangetype.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.2)
3  * Copyright (C) 2014 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 java.util.Vector;
24
25 import uk.ac.vamsas.client.Vobject;
26 import uk.ac.vamsas.objects.core.Local;
27 import uk.ac.vamsas.objects.core.MapType;
28 import uk.ac.vamsas.objects.core.Mapped;
29 import uk.ac.vamsas.objects.core.RangeType;
30 import uk.ac.vamsas.objects.core.Seg;
31 import jalview.io.VamsasAppDatastore;
32 import jalview.util.MessageManager;
33
34 /**
35  * Enhances DatastoreItem objects with additional functions to do with RangeType
36  * objects
37  * 
38  * @author JimP
39  * 
40  */
41 public abstract class Rangetype extends DatastoreItem
42 {
43
44   public Rangetype()
45   {
46     super();
47   }
48
49   public Rangetype(VamsasAppDatastore datastore)
50   {
51     super(datastore);
52   }
53
54   public Rangetype(VamsasAppDatastore datastore, Vobject vobj, Class jvClass)
55   {
56     super(datastore, vobj, jvClass);
57   }
58
59   public Rangetype(VamsasAppDatastore datastore, Object jvobj, Class vClass)
60   {
61     super(datastore, jvobj, vClass);
62   }
63
64   /**
65    * get real bounds of a RangeType's specification. start and end are an
66    * inclusive range within which all segments and positions lie. TODO: refactor
67    * to vamsas utils
68    * 
69    * @param dseta
70    * @return int[] { start, end}
71    */
72   protected int[] getBounds(RangeType dseta)
73   {
74     if (dseta != null)
75     {
76       int[] se = null;
77       if (dseta.getSegCount() > 0 && dseta.getPosCount() > 0)
78       {
79         throw new Error(MessageManager.getString("error.invalid_vamsas_rangetype_cannot_resolve_lists"));
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(MessageManager.getString("error.invalid_vamsas_rangetype_cannot_resolve_lists"));
138       }
139       if (dseta.getSegCount() > 0)
140       {
141         for (int s = 0, sSize = dseta.getSegCount(); s < sSize; s++)
142         {
143           se = getSegRange(dseta.getSeg(s), false);
144           int se_end = se[1 - se[2]] + (se[2] == 0 ? 1 : -1);
145           for (int p = se[se[2]]; p != se_end; p += se[2] == 0 ? 1 : -1)
146           {
147             posList.add(new Integer(p));
148           }
149         }
150       }
151       else if (dseta.getPosCount() > 0)
152       {
153         int pos = dseta.getPos(0).getI();
154
155         for (int p = 0, pSize = dseta.getPosCount(); p < pSize; p++)
156         {
157           pos = dseta.getPos(p).getI();
158           posList.add(new Integer(pos));
159         }
160       }
161     }
162     if (posList != null && posList.size() > 0)
163     {
164       int[] range = new int[posList.size()];
165       for (int i = 0; i < range.length; i++)
166       {
167         range[i] = ((Integer) posList.elementAt(i)).intValue();
168       }
169       posList.clear();
170       return range;
171     }
172     return null;
173   }
174
175   protected int[] getIntervals(RangeType range)
176   {
177     int[] intervals = null;
178     Vector posList = new Vector();
179     if (range != null)
180     {
181       int[] se = null;
182       if (range.getSegCount() > 0 && range.getPosCount() > 0)
183       {
184         throw new Error(MessageManager.getString("error.invalid_vamsas_rangetype_cannot_resolve_lists"));
185       }
186       if (range.getSegCount() > 0)
187       {
188         for (int s = 0, sSize = range.getSegCount(); s < sSize; s++)
189         {
190           se = getSegRange(range.getSeg(s), false);
191           posList.addElement(new Integer(se[0]));
192           posList.addElement(new Integer(se[1]));
193         }
194       }
195       else if (range.getPosCount() > 0)
196       {
197         int pos = range.getPos(0).getI();
198
199         for (int p = 0, pSize = range.getPosCount(); p < pSize; p++)
200         {
201           pos = range.getPos(p).getI();
202           posList.add(new Integer(pos));
203           posList.add(new Integer(pos));
204         }
205       }
206     }
207     if (posList != null && posList.size() > 0)
208     {
209       intervals = new int[posList.size()];
210       java.util.Enumeration e = posList.elements();
211       int i = 0;
212       while (e.hasMoreElements())
213       {
214         intervals[i++] = ((Integer) e.nextElement()).intValue();
215       }
216     }
217     return intervals;
218   }
219
220   /**
221    * initialise a range type object from a set of start/end inclusive intervals
222    * 
223    * @param mrt
224    * @param range
225    */
226   protected void initRangeType(RangeType mrt, int[] range)
227   {
228     for (int i = 0; i < range.length; i += 2)
229     {
230       Seg vSeg = new Seg();
231       vSeg.setStart(range[i]);
232       vSeg.setEnd(range[i + 1]);
233       vSeg.setInclusive(true);
234       mrt.addSeg(vSeg);
235     }
236   }
237
238   /**
239    * 
240    * @param maprange
241    *          where the from range is the local mapped range, and the to range
242    *          is the 'mapped' range in the MapRangeType
243    * @param default unit for local
244    * @param default unit for mapped
245    * @return MapList
246    */
247   protected jalview.util.MapList parsemapType(MapType maprange, int localu,
248           int mappedu)
249   {
250     jalview.util.MapList ml = null;
251     int[] localRange = getIntervals(maprange.getLocal());
252     int[] mappedRange = getIntervals(maprange.getMapped());
253     long lu = maprange.getLocal().hasUnit() ? maprange.getLocal().getUnit()
254             : localu;
255     long mu = maprange.getMapped().hasUnit() ? maprange.getMapped()
256             .getUnit() : mappedu;
257     ml = new jalview.util.MapList(localRange, mappedRange, (int) lu,
258             (int) mu);
259     return ml;
260   }
261
262   protected jalview.util.MapList parsemapType(MapType map)
263   {
264     if (!map.getLocal().hasUnit() || map.getMapped().hasUnit())
265     {
266       jalview.bin.Cache.log
267               .warn("using default mapping length of 1:1 for map "
268                       + (map.isRegistered() ? map.getVorbaId().toString()
269                               : ("<no Id registered> " + map.toString())));
270     }
271     return parsemapType(map, 1, 1);
272   }
273
274   /**
275    * initialise a MapType object from a MapList object.
276    * 
277    * @param maprange
278    * @param ml
279    * @param setUnits
280    */
281   protected void initMapType(MapType maprange, jalview.util.MapList ml,
282           boolean setUnits)
283   {
284     initMapType(maprange, ml, setUnits, false);
285   }
286
287   /**
288    * 
289    * @param maprange
290    * @param ml
291    * @param setUnits
292    * @param reverse
293    *          - reverse MapList mapping for Local and Mapped ranges and units
294    */
295   protected void initMapType(MapType maprange, jalview.util.MapList ml,
296           boolean setUnits, boolean reverse)
297   {
298     if (ml == null)
299     {
300       throw new Error(MessageManager.getString("error.implementation_error_maplist_is_null"));
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 }