/* * Jalview - A Sequence Alignment Editor and Viewer * Copyright (C) 2007 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ package jalview.util; import java.util.*; /** * MapList * Simple way of bijectively mapping a non-contiguous linear range to another non-contiguous linear range * Use at your own risk! * TODO: efficient implementation of private posMap method * TODO: test/ensure that sense of from and to ratio start position is conserved (codon start position recovery) * TODO: optimize to use int[][] arrays rather than vectors. */ public class MapList { /* (non-Javadoc) * @see java.lang.Object#clone() */ protected Object clone() throws CloneNotSupportedException { // TODO Auto-generated method stub return super.clone(); } /* (non-Javadoc) * @see java.lang.Object#equals(java.lang.Object) */ public boolean equals(MapList obj) { if (obj==this) return true; if (obj!=null && obj.fromRatio==fromRatio && obj.toRatio==toRatio && obj.fromShifts!=null && obj.toShifts!=null) { int i,iSize=fromShifts.size(),j,jSize=obj.fromShifts.size(); if (iSize!=jSize) return false; for (i=0,iSize=fromShifts.size(),j=0, jSize=obj.fromShifts.size(); ipos) limits[0]=pos; if (limits[1]=ivSize) { return null; } int[] intv=(int[]) intVals.elementAt(iv++); int from=intv[0],to=intv[1]; if (from > to) { from = intv[1]; to=intv[0]; } while (ivto) { to=intv[0]; } if (intv[1]>to) { to=intv[1]; } } int tF=0,tT=0; int mp[][] = new int[to-from+2][]; for (int i = 0; i < mp.length; i++) { int[] m = shift(i+from,intVals,ratio,toIntVals, toRatio); if (m != null) { if (i == 0) { tF=tT=m[0]; } else { if (m[0] < tF) { tF=m[0]; } if (m[0] > tT) { tT=m[0]; } } } mp[i] = m; } int[][] map = new int[][] { new int[] { from, to, tF, tT}, new int[to - from + 2]}; map[0][2] = tF; map[0][3] = tT; for (int i = 0; i < mp.length; i++) { if (mp[i] != null) { map[1][i] = mp[i][0]-tF; } else { map[1][i] = -1; // indicates an out of range mapping } } return map; } /** * addShift * @param pos start position for shift (in original reference frame) * @param shift length of shift * public void addShift(int pos, int shift) { int sidx = 0; int[] rshift=null; while (sidx= intv[0] && pos <= intv[1]) { return new int[] { count + pos - intv[0] + 1, +1}; } else { count+=intv[1]-intv[0]+1; } } else { if (pos >= intv[1] && pos <= intv[0]) { return new int[] { count + intv[0] - pos + 1, -1}; } else { count+=intv[0]-intv[1]+1; } } } return null; } /** * count out pos positions into a series of intervals and return the position * @param intVals * @param pos * @return position pos in interval set */ private int[] countToPos(Vector intVals, int pos) { int count = 0, diff = 0, iv=0,ivSize=intVals.size(), intv[] = { 0, 0}; while (iv= 0) { if (pos <= count + 1 + diff) { return new int[] { pos - count - 1 + intv[0], +1}; } else { count+=1+diff; } } else { if (pos <= count + 1 - diff) { return new int[] { intv[0] - (pos - count - 1), -1}; } else { count+=1-diff; } } } return null;//(diff<0) ? (intv[1]-1) : (intv[0]+1); } /** * find series of intervals mapping from start-end in the From map. * @param start position in to map * @param end position in to map * @return series of ranges in from map */ public int[] locateInFrom(int start, int end) { // inefficient implementation int fromStart[] = shiftTo(start); int fromEnd[] = shiftTo(end); if (fromStart==null || fromEnd==null) return null; int iv[] = getIntervals(fromShifts, fromStart, fromEnd,fromRatio); return iv; } /** * find series of intervals mapping from start-end in the to map. * @param start position in from map * @param end position in from map * @return series of ranges in to map */ public int[] locateInTo(int start, int end) { // inefficient implementation int toStart[] = shiftFrom(start); int toEnd[] = shiftFrom(end); if (toStart==null || toEnd==null) return null; int iv[] = getIntervals(toShifts, toStart, toEnd, toRatio); return iv; } /** * like shift - except returns the intervals in the given vector of shifts which were spanned * in traversing fromStart to fromEnd * @param fromShifts2 * @param fromStart * @param fromEnd * @param fromRatio2 * @return */ private int[] getIntervals(Vector fromShifts2, int[] fromStart, int[] fromEnd, int fromRatio2) { // correct for word direction for start and end int startpos = fromStart[0]+fromStart[2]*(fromRatio2-1); int endpos = fromEnd[0]+fromEnd[2]*(fromRatio2-1); int intv=0,intvSize= fromShifts2.size(); int iv[],i=0,fs=-1,fe=-1; // containing intervals while (intv=iv[0] && startpos<=iv[1]) { fs = i; } if (fe==-1 && endpos>=iv[0] && endpos<=iv[1]) { fe = i; } } else { if (fs==-1 && startpos<=iv[0] && startpos>=iv[1]) { fs = i; } if (fe==-1 && endpos<=iv[0] && endpos>=iv[1]) { fe = i; } } i++; } if (fs==fe && fe==-1) return null; Vector ranges=new Vector(); if (fs<=fe) { intv = fs; i=fs; // truncate initial interval iv = (int[]) fromShifts2.elementAt(intv++); iv = new int[] { iv[0], iv[1]};// clone if (i==fs) iv[0] = startpos; while (i!=fe) { ranges.addElement(iv); // add initial range iv = (int[]) fromShifts2.elementAt(intv++); // get next interval iv = new int[] { iv[0], iv[1]};// clone i++; } if (i==fe) iv[1] = endpos; ranges.addElement(iv); // add only - or final range } else { // walk from end of interval. i=fromShifts2.size()-1; while (i>fs) { i--; } iv = (int[]) fromShifts2.elementAt(i); iv = new int[] { iv[1], iv[0]};// reverse and clone // truncate initial interval if (i==fs) { iv[0] = startpos; } while (i!=fe) { ranges.addElement(iv); // add (truncated) reversed interval iv = (int[]) fromShifts2.elementAt(--i); iv = new int[] { iv[1], iv[0] }; // reverse and clone } if (i==fe) { // interval is already reversed iv[1] = endpos; } ranges.addElement(iv); // add only - or final range } // create array of start end intervals. int[] range = null; if (ranges!=null && ranges.size()>0) { range = new int[ranges.size()*2]; intv = 0; intvSize=ranges.size(); i=0; while (intv" + toofrom[0]); } System.out.println("ShiftTo(" + too[0] + ")==" + toofrom[0] + " % " + toofrom[1]+" ("+toofrom[2]+")"); } else { System.out.println("ShiftTo(" + too[0] + ")==" + "NaN! - not Bijective Mapping!"); } } } int mmap[][] = ml.makeFromMap(); System.out.println("FromMap : (" + mmap[0][0] + " " + mmap[0][1] + " " + mmap[0][2] + " " + mmap[0][3] + " "); for (int i = 1; i <= mmap[1].length; i++) { if (mmap[1][i - 1] == -1) { System.out.print(i+"=XXX"); } else { System.out.print(i+"="+(mmap[0][2]+mmap[1][i-1])); } if (i % 20==0) { System.out.print("\n"); } else { System.out.print(","); } } //test range function System.out.print("\nTest locateInFrom\n"); { int f=mmap[0][2],t=mmap[0][3]; while (f