--- /dev/null
+package uk.ac.vamsas.objects.utils;\r
+\r
+import java.util.Vector;\r
+\r
+\r
+import uk.ac.vamsas.objects.core.RangeType;\r
+import uk.ac.vamsas.objects.core.Seg;\r
+\r
+public class Range {\r
+\r
+ /**\r
+ * get start<end range of segment, adjusting for inclusivity flag and\r
+ * polarity.\r
+ *\r
+ * @param visSeg\r
+ * @param ensureDirection when true - always ensure start is less than end.\r
+ * @return int[] { start, end, direction} where direction==1 for range running from end to start.\r
+ */\r
+ public static int[] getSegRange(Seg visSeg, boolean ensureDirection)\r
+ {\r
+ boolean incl = visSeg.getInclusive();\r
+ // adjust for inclusive flag.\r
+ int pol = (visSeg.getStart() <= visSeg.getEnd()) ? 1 : -1; // polarity of\r
+ // region.\r
+ int start = visSeg.getStart() + (incl ? 0 : pol);\r
+ int end = visSeg.getEnd() + (incl ? 0 : -pol);\r
+ if (ensureDirection && pol == -1)\r
+ {\r
+ // jalview doesn't deal with inverted ranges, yet.\r
+ int t = end;\r
+ end = start;\r
+ start = t;\r
+ }\r
+ return new int[]\r
+ {\r
+ start, end, pol < 0 ? 1 : 0};\r
+ }\r
+\r
+ /**\r
+ * get real bounds of a RangeType's specification. start and end are an\r
+ * inclusive range within which all segments and positions lie.\r
+ * TODO: refactor to vamsas utils\r
+ * @param dseta\r
+ * @return int[] { start, end}\r
+ */\r
+ public static int[] getBounds(RangeType dseta)\r
+ {\r
+ if (dseta != null)\r
+ {\r
+ int[] se = null;\r
+ if (dseta.getSegCount() > 0 && dseta.getPosCount() > 0)\r
+ {\r
+ throw new Error("Invalid vamsas RangeType - cannot resolve both lists of Pos and Seg from choice!");\r
+ }\r
+ if (dseta.getSegCount() > 0)\r
+ {\r
+ se = getSegRange(dseta.getSeg(0), true);\r
+ for (int s = 1, sSize = dseta.getSegCount(); s < sSize; s++)\r
+ {\r
+ int nse[] = getSegRange(dseta.getSeg(s), true);\r
+ if (se[0] > nse[0])\r
+ {\r
+ se[0] = nse[0];\r
+ }\r
+ if (se[1] < nse[1])\r
+ {\r
+ se[1] = nse[1];\r
+ }\r
+ }\r
+ }\r
+ if (dseta.getPosCount() > 0)\r
+ {\r
+ // could do a polarity for pos range too. and pass back indication of discontinuities.\r
+ int pos = dseta.getPos(0).getI();\r
+ se = new int[]\r
+ {\r
+ pos, pos};\r
+ for (int p = 0, pSize = dseta.getPosCount(); p < pSize; p++)\r
+ {\r
+ pos = dseta.getPos(p).getI();\r
+ if (se[0] > pos)\r
+ {\r
+ se[0] = pos;\r
+ }\r
+ if (se[1] < pos)\r
+ {\r
+ se[1] = pos;\r
+ }\r
+ }\r
+ }\r
+ return se;\r
+ }\r
+ return null;\r
+ }\r
+\r
+ /**\r
+ * map from a rangeType's internal frame to the referenced object's coordinate frame.\r
+ * @param dseta\r
+ * @return int [] { ref(pos)...} for all pos in rangeType's frame.\r
+ */\r
+ public static int[] getMapping(RangeType dseta)\r
+ {\r
+ Vector posList = new Vector();\r
+ if (dseta != null)\r
+ {\r
+ int[] se = null;\r
+ if (dseta.getSegCount() > 0 && dseta.getPosCount() > 0)\r
+ {\r
+ throw new Error("Invalid vamsas RangeType - cannot resolve both lists of Pos and Seg from choice!");\r
+ }\r
+ if (dseta.getSegCount() > 0)\r
+ {\r
+ for (int s = 0, sSize = dseta.getSegCount(); s < sSize; s++)\r
+ {\r
+ se = getSegRange(dseta.getSeg(s), false);\r
+ int se_end = se[1 - se[2]] + (se[2] == 0 ? 1 : -1);\r
+ for (int p = se[se[2]]; p != se_end; p += se[2] == 0 ? 1 : -1)\r
+ {\r
+ posList.add(new Integer(p));\r
+ }\r
+ }\r
+ }\r
+ else if (dseta.getPosCount() > 0)\r
+ {\r
+ int pos = dseta.getPos(0).getI();\r
+\r
+ for (int p = 0, pSize = dseta.getPosCount(); p < pSize; p++)\r
+ {\r
+ pos = dseta.getPos(p).getI();\r
+ posList.add(new Integer(pos));\r
+ }\r
+ }\r
+ }\r
+ if (posList != null && posList.size() > 0)\r
+ {\r
+ int[] range = new int[posList.size()];\r
+ for (int i = 0; i < range.length; i++)\r
+ {\r
+ range[i] = ( (Integer) posList.elementAt(i)).intValue();\r
+ }\r
+ posList.clear();\r
+ return range;\r
+ }\r
+ return null;\r
+ }\r
+}\r