2 * This file is part of the Vamsas Client version 0.1.
\r
3 * Copyright 2009 by Jim Procter, Iain Milne, Pierre Marguerite,
\r
4 * Andrew Waterhouse and Dominik Lindner.
\r
6 * Earlier versions have also been incorporated into Jalview version 2.4
\r
7 * since 2008, and TOPALi version 2 since 2007.
\r
9 * The Vamsas Client is free software: you can redistribute it and/or modify
\r
10 * it under the terms of the GNU Lesser General Public License as published by
\r
11 * the Free Software Foundation, either version 3 of the License, or
\r
12 * (at your option) any later version.
\r
14 * The Vamsas Client is distributed in the hope that it will be useful,
\r
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
17 * GNU Lesser General Public License for more details.
\r
19 * You should have received a copy of the GNU Lesser General Public License
\r
20 * along with the Vamsas Client. If not, see <http://www.gnu.org/licenses/>.
\r
22 package uk.ac.vamsas.objects.utils;
\r
24 import java.util.Vector;
\r
26 import uk.ac.vamsas.objects.core.Local;
\r
27 import uk.ac.vamsas.objects.core.MapType;
\r
28 import uk.ac.vamsas.objects.core.Mapped;
\r
29 import uk.ac.vamsas.objects.core.RangeType;
\r
30 import uk.ac.vamsas.objects.core.Seg;
\r
33 * Utilities for working with RangeType and MapType objects. Derived from bitter
\r
39 public class Range {
\r
40 static org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory
\r
41 .getFactory().getLog(Range.class);
\r
44 * get start<end range of segment, adjusting for inclusivity flag and
\r
48 * @param ensureDirection
\r
49 * when true - always ensure start is less than end.
\r
50 * @return int[] { start, end, direction} where direction==1 for range running
\r
51 * from end to start.
\r
53 public static int[] getSegRange(Seg visSeg, boolean ensureDirection) {
\r
54 boolean incl = visSeg.getInclusive();
\r
55 // adjust for inclusive flag.
\r
56 int pol = (visSeg.getStart() <= visSeg.getEnd()) ? 1 : -1; // polarity of
\r
58 int start = visSeg.getStart() + (incl ? 0 : pol);
\r
59 int end = visSeg.getEnd() + (incl ? 0 : -pol);
\r
60 if (ensureDirection && pol == -1) {
\r
61 // jalview doesn't deal with inverted ranges, yet.
\r
66 return new int[] { start, end, pol < 0 ? 1 : 0 };
\r
70 * get real bounds of a RangeType's specification. start and end are an
\r
71 * inclusive range within which all segments and positions lie. TODO: refactor
\r
75 * @return int[] { start, end}
\r
77 public static int[] getBounds(RangeType dseta) {
\r
78 if (dseta != null) {
\r
80 if (dseta.getSegCount() > 0 && dseta.getPosCount() > 0) {
\r
82 "Invalid vamsas RangeType - cannot resolve both lists of Pos and Seg from choice!");
\r
84 if (dseta.getSegCount() > 0) {
\r
85 se = getSegRange(dseta.getSeg(0), true);
\r
86 for (int s = 1, sSize = dseta.getSegCount(); s < sSize; s++) {
\r
87 int nse[] = getSegRange(dseta.getSeg(s), true);
\r
88 if (se[0] > nse[0]) {
\r
91 if (se[1] < nse[1]) {
\r
96 if (dseta.getPosCount() > 0) {
\r
97 // could do a polarity for pos range too. and pass back indication of
\r
99 int pos = dseta.getPos(0).getI();
\r
100 se = new int[] { pos, pos };
\r
101 for (int p = 1, pSize = dseta.getPosCount(); p < pSize; p++) {
\r
102 pos = dseta.getPos(p).getI();
\r
117 * map from a rangeType's internal frame to the referenced object's coordinate
\r
121 * @return int [] { ref(pos)...} for all pos in rangeType's frame.
\r
123 public static int[] getMapping(RangeType dseta) {
\r
124 Vector posList = new Vector();
\r
125 if (dseta != null) {
\r
127 if (dseta.getSegCount() > 0 && dseta.getPosCount() > 0) {
\r
129 "Invalid vamsas RangeType - cannot resolve both lists of Pos and Seg from choice!");
\r
131 if (dseta.getSegCount() > 0) {
\r
132 for (int s = 0, sSize = dseta.getSegCount(); s < sSize; s++) {
\r
133 se = getSegRange(dseta.getSeg(s), false);
\r
134 int se_end = se[1 - se[2]] + (se[2] == 0 ? 1 : -1);
\r
135 for (int p = se[se[2]]; p != se_end; p += se[2] == 0 ? 1 : -1) {
\r
136 posList.add(new Integer(p));
\r
139 } else if (dseta.getPosCount() > 0) {
\r
140 int pos = dseta.getPos(0).getI();
\r
142 for (int p = 0, pSize = dseta.getPosCount(); p < pSize; p++) {
\r
143 pos = dseta.getPos(p).getI();
\r
144 posList.add(new Integer(pos));
\r
148 if (posList != null && posList.size() > 0) {
\r
149 int[] range = new int[posList.size()];
\r
150 for (int i = 0; i < range.length; i++) {
\r
151 range[i] = ((Integer) posList.elementAt(i)).intValue();
\r
159 public static int[] getIntervals(RangeType range) {
\r
160 int[] intervals = null;
\r
161 Vector posList = new Vector();
\r
162 if (range != null) {
\r
164 if (range.getSegCount() > 0 && range.getPosCount() > 0) {
\r
166 "Invalid vamsas RangeType - cannot resolve both lists of Pos and Seg from choice!");
\r
168 if (range.getSegCount() > 0) {
\r
169 for (int s = 0, sSize = range.getSegCount(); s < sSize; s++) {
\r
170 se = getSegRange(range.getSeg(s), false);
\r
171 posList.addElement(new Integer(se[0]));
\r
172 posList.addElement(new Integer(se[1]));
\r
174 } else if (range.getPosCount() > 0) {
\r
175 int pos = range.getPos(0).getI();
\r
176 for (int p = 0, pSize = range.getPosCount(); p < pSize; p++) {
\r
177 pos = range.getPos(p).getI();
\r
178 posList.add(new Integer(pos));
\r
179 posList.add(new Integer(pos));
\r
183 if (posList != null && posList.size() > 0) {
\r
184 intervals = new int[posList.size()];
\r
185 java.util.Enumeration e = posList.elements();
\r
187 while (e.hasMoreElements()) {
\r
188 intervals[i++] = ((Integer) e.nextElement()).intValue();
\r
195 * initialise a range type object from a set of start/end inclusive intervals
\r
200 public static void initRangeType(RangeType mrt, int[] range) {
\r
201 for (int i = 0; i < range.length; i += 2) {
\r
202 Seg vSeg = new Seg();
\r
203 vSeg.setStart(range[i]);
\r
204 vSeg.setEnd(range[i + 1]);
\r
205 vSeg.setInclusive(true);
\r
213 * where the from range is the local mapped range, and the to range
\r
214 * is the 'mapped' range in the MapRangeType
\r
215 * @param default unit for local
\r
216 * @param default unit for mapped
\r
219 public static MapList parsemapType(MapType maprange, int localu, int mappedu) {
\r
221 int[] localRange = getIntervals(maprange.getLocal());
\r
222 int[] mappedRange = getIntervals(maprange.getMapped());
\r
223 long lu = maprange.getLocal().hasUnit() ? maprange.getLocal().getUnit()
\r
225 long mu = maprange.getMapped().hasUnit() ? maprange.getMapped().getUnit()
\r
227 ml = new MapList(localRange, mappedRange, (int) lu, (int) mu);
\r
232 * Parse map with default units of 1,1
\r
235 * @return MapList representing map
\r
237 public static MapList parsemapType(MapType map) {
\r
238 if (!map.getLocal().hasUnit() || !map.getMapped().hasUnit()) {
\r
239 if (log.isDebugEnabled()) {
\r
240 log.debug("using default mapping length of 1:1 for map "
\r
241 + (map.isRegistered() ? map.getVorbaId().toString()
\r
242 : ("<no Id registered> " + map.toString())));
\r
245 return parsemapType(map, 1, 1);
\r
249 * initialise a MapType object from a MapList object.
\r
255 public static void initMapType(MapType maprange, MapList ml, boolean setUnits) {
\r
256 initMapType(maprange, ml, setUnits, false);
\r
265 * - reverse MapList mapping for Local and Mapped ranges and units
\r
267 public static void initMapType(MapType maprange, MapList ml,
\r
268 boolean setUnits, boolean reverse) {
\r
269 maprange.setLocal(new Local());
\r
270 maprange.setMapped(new Mapped());
\r
272 initRangeType(maprange.getLocal(), ml.getFromRanges());
\r
273 initRangeType(maprange.getMapped(), ml.getToRanges());
\r
275 initRangeType(maprange.getLocal(), ml.getToRanges());
\r
276 initRangeType(maprange.getMapped(), ml.getFromRanges());
\r
280 maprange.getLocal().setUnit(ml.getFromRatio());
\r
281 maprange.getMapped().setUnit(ml.getToRatio());
\r
283 maprange.getLocal().setUnit(ml.getToRatio());
\r
284 maprange.getMapped().setUnit(ml.getFromRatio());
\r