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