From 1698842ec6755d1995dae7c1a590efbfc8f6e4d5 Mon Sep 17 00:00:00 2001 From: jprocter Date: Mon, 19 Mar 2007 13:42:40 +0000 Subject: [PATCH] mapping implemented by MapList added to DBRefEntry. --- src/jalview/datamodel/DBRefEntry.java | 144 ++++++---- src/jalview/datamodel/Mapping.java | 201 ++++++++++++++ src/jalview/util/MapList.java | 484 ++++++++++++++++++++++++++------- 3 files changed, 691 insertions(+), 138 deletions(-) create mode 100644 src/jalview/datamodel/Mapping.java diff --git a/src/jalview/datamodel/DBRefEntry.java b/src/jalview/datamodel/DBRefEntry.java index c35c8c2..b5a9ded 100755 --- a/src/jalview/datamodel/DBRefEntry.java +++ b/src/jalview/datamodel/DBRefEntry.java @@ -1,47 +1,97 @@ -/* - * 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.datamodel; - -public class DBRefEntry -{ - String source, version, accessionId; - - public DBRefEntry(String source, String version, String accessionId) - { - this.source = source; - this.version = version; - this.accessionId = accessionId; - } - - public String getSource() - { - return source; - } - - public String getVersion() - { - return version; - } - - public String getAccessionId() - { - return accessionId; - } - -} +/* + * 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.datamodel; + +public class DBRefEntry +{ + String source="", version="", accessionId=""; + /** + * maps from associated sequence to the database sequence's coordinate system + */ + Mapping map=null; + public DBRefEntry() { + + } + public DBRefEntry(String source, String version, String accessionId) + { + this.source = source; + this.version = version; + this.accessionId = accessionId; + } + public boolean equals(DBRefEntry entry) { + if (entry==this) + return true; + if (entry==null) + return false; + if ((source!=null && entry.source!=null && source.equals(entry.source)) + && + (accessionId!=null && entry.accessionId!=null && accessionId.equals(entry.accessionId)) + && + (version!=null && entry.version!=null && version.equals(entry.version)) + && + ((map==null && entry.map==null) || (map!=null && entry.map!=null && map.equals(entry.map)))) { + return true; + } + return false; + } + public String getSource() + { + return source; + } + + public String getVersion() + { + return version; + } + + public String getAccessionId() + { + return accessionId; + } +/** + * @param accessionId the accessionId to set + */ +public void setAccessionId(String accessionId) { + this.accessionId = accessionId; +} +/** + * @param source the source to set + */ +public void setSource(String source) { + this.source = source; +} +/** + * @param version the version to set + */ +public void setVersion(String version) { + this.version = version; +} +/** + * @return the map + */ +public Mapping getMap() { + return map; +} +/** + * @param map the map to set + */ +public void setMap(Mapping map) { + this.map = map; +} +} diff --git a/src/jalview/datamodel/Mapping.java b/src/jalview/datamodel/Mapping.java new file mode 100644 index 0000000..4daf7d4 --- /dev/null +++ b/src/jalview/datamodel/Mapping.java @@ -0,0 +1,201 @@ +package jalview.datamodel; + +import jalview.util.MapList; + +public class Mapping { + /** + * Contains the + * start-end pairs mapping from + * the associated sequence to the + * sequence in the database + * coordinate system + * it also takes care of step difference between coordinate systems + */ + MapList map=null; + /** + * The seuqence that map maps the associated seuqence to (if any). + */ + SequenceI to=null; + public Mapping(MapList map) { + super(); + this.map = map; + } + /** + * create a new mapping from + * @param exon int[] {start,end,start,end} series on associated sequence + * @param is int[] {start,end,...} ranges on the reference frame being mapped to + * @param i step size on associated sequence + * @param j step size on mapped frame + */ + public Mapping(SequenceI to, int[] exon, int[] is, int i, int j) + { + map = new MapList(exon, is, i, j); + } + + /** + * @return the map + */ + public MapList getMap() { + return map; + } + + /** + * @param map the map to set + */ + public void setMap(MapList map) { + this.map = map; + } + public boolean equals(Mapping other) { + if (other==null) + return false; + if (other==this) + return true; + if ((map!=null && other.map==null) || (map==null && other.map!=null)) + return false; + if (map.equals(other.map)) + return true; + return false; + } + /** + * get the 'initial' position in the associated + * sequence for a position in the mapped reference frame + * @param mpos + * @return + */ + public int getPosition(int mpos) + { + if (map!=null) { + int[] mp = map.shiftTo(mpos); + if (mp!=null) + { + return mp[0]; + } + } + return mpos; + } + public int[] getWord(int mpos) { + if (map!=null) { + int[] mp=map.shiftTo(mpos); + if (mp!=null) { + return new int[] {mp[0], mp[0]+mp[2]*(map.getFromRatio()-1)}; + } + } + return null; + } + /** + * width of mapped unit in associated sequence + * + */ + public int getWidth() { + if (map!=null) { + return map.getFromRatio(); + } + return 1; + } + + /** + * width of unit in mapped reference frame + * @return + */ + public int getMappedWidth() { + if (map!=null) { + return map.getToRatio(); + } + return 1; + } + /** + * get mapped position in the associated + * reference frame for position pos in the + * associated sequence. + * @param pos + * @return + */ + public int getMappedPosition(int pos) { + if (map!=null) { + int[] mp = map.shiftFrom(pos); + if (mp!=null) + { + return mp[0]; + } + } + return pos; + } + public int[] getMappedWord(int pos) { + if (map!=null) { + int[] mp = map.shiftFrom(pos); + if (mp!=null) + { + return new int[] { mp[0], mp[0]+mp[2]*(map.getToRatio()-1)}; + } + } + return null; + } + /** + * locates the region of feature f in the associated sequence's reference frame + * @param f + * @return one or more features corresponding to f + */ + public SequenceFeature[] locateFeature(SequenceFeature f) + { + // this is a stopgap - features broken over exon boundaries will not be + // broken into a collection of feature fragments. + // TODO: implement creation of several features from a single feature on a discontinuously mapped seuqence + // need a function like int [] fromrange = map.getRange(from,to) + // need to make subgrouped sequence features. + if (true) { + if (map!=null) { + int[] frange = map.locateInFrom(f.getBegin(), f.getEnd()); + SequenceFeature[] vf = new SequenceFeature[frange.length/2]; + for (int i=0,v=0;i2) + vf[v].setDescription(f.getDescription() +"\nPart "+v); + } + return vf; + } + } + if (false){ + int[] word = getWord(f.getBegin()); + if (word[0]word[1]) + { + f.setEnd(word[0]); + } else { + f.setEnd(word[1]); + } + } + // give up and just return the feature. + return new SequenceFeature[] { f }; + } + + /** + * return a series of contigs on the associated sequence corresponding to + * the from,to interval on the mapped reference frame + * @param from + * @param to + * @return + */ + public int[] locateRange(int from, int to) { + //TODO + return null; + } + /** + * return a series of contigs on the mapped reference frame corresponding to + * the from,to interval on the associated sequence + * @param from + * @param to + * @return + */ + public int[] locateMappedRange(int from, int to) { + //TODO + return null; + } +} diff --git a/src/jalview/util/MapList.java b/src/jalview/util/MapList.java index 215ece9..5da89b0 100644 --- a/src/jalview/util/MapList.java +++ b/src/jalview/util/MapList.java @@ -30,28 +30,109 @@ import java.util.*; */ 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) { + Iterator i,j; + for (i=fromShifts.iterator(),j=obj.fromShifts.iterator(); i.hasNext();) { + int[] mi=(int[]) i.next(); + if (!j.hasNext()) + return false; + int[] mj=(int[]) j.next(); + if (mi[0]!=mj[0] || mi[1]!=mj[1]) + return false; + } + if (j.hasNext()) + return false; + for (i=toShifts.iterator(),j=obj.toShifts.iterator(); i.hasNext();) { + int[] mi=(int[]) i.next(); + if (!j.hasNext()) + return false; + int[] mj=(int[]) j.next(); + if (mi[0]!=mj[0] || mi[1]!=mj[1]) + return false; + } + if (j.hasNext()) + return false; + return true; + } + return false; + } public Vector fromShifts; public Vector toShifts; int fromRatio; // number of steps in fromShifts to one toRatio unit int toRatio; // number of steps in toShifts to one fromRatio + /** + * lowest and highest value in the from Map + */ + int[] fromRange=null; + /** + * lowest and highest value in the to Map + */ + int[] toRange=null; + public int getFromRatio() + { + return fromRatio; + } + public int getToRatio() + { + return toRatio; + } + public int getFromLowest() { + return fromRange[0]; + } + public int getFromHighest() { + return fromRange[1]; + } + public int getToLowest() { + return toRange[0]; + } + public int getToHighest() { + return toRange[1]; + } + private void ensureRange(int[] limits, int pos) { + if (limits[0]>pos) + limits[0]=pos; + if (limits[1] to) { from = intv[1]; - to = intv[0]; + to=intv[0]; } while (iv.hasNext()) { intv = (int[]) iv.next(); - if (intv[0] < from) + if (intv[0] to) + if (intv[0]>to) { - to = intv[0]; + to=intv[0]; } - if (intv[1] > to) + if (intv[1]>to) { - to = intv[1]; + to=intv[1]; } } - int tF = 0, tT = 0; - int mp[][] = new int[to - from + 2][]; + 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); + int[] m = shift(i+from,intVals,ratio,toIntVals, toRatio); if (m != null) { if (i == 0) { - tF = tT = m[0]; + tF=tT=m[0]; } else { if (m[0] < tF) { - tF = m[0]; + tF=m[0]; } if (m[0] > tT) { - tT = m[0]; + tT=m[0]; } } } mp[i] = m; } int[][] map = new int[][] - { + { new int[] - { - from, to, tF, tT}, new int[to - from + 2]}; + { + from, to, tF, tT}, new int[to - from + 2]}; map[0][2] = tF; map[0][3] = tT; @@ -148,7 +227,7 @@ public class MapList { if (mp[i] != null) { - map[1][i] = mp[i][0] - tF; + map[1][i] = mp[i][0]-tF; } else { @@ -157,29 +236,28 @@ public class MapList } 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) - { + 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; + count+=intv[1]-intv[0]+1; } } else @@ -255,18 +331,17 @@ public class MapList if (pos >= intv[1] && pos <= intv[0]) { return new int[] - { + { count + intv[0] - pos + 1, -1}; } else { - count += intv[0] - intv[1] + 1; + count+=intv[0]-intv[1]+1; } } } return null; } - /** * count out pos positions into a series of intervals and return the position * @param intVals @@ -276,23 +351,23 @@ public class MapList private int[] countToPos(Iterator intVals, int pos) { int count = 0, diff = 0, intv[] = - { + { 0, 0}; while (intVals.hasNext()) { - intv = (int[]) intVals.next(); - diff = intv[1] - intv[0]; + intv = (int[])intVals.next(); + diff = intv[1]-intv[0]; if (diff >= 0) { if (pos <= count + 1 + diff) { return new int[] - { + { pos - count - 1 + intv[0], +1}; } else { - count += 1 + diff; + count+=1+diff; } } else @@ -300,65 +375,258 @@ public class MapList if (pos <= count + 1 - diff) { return new int[] - { + { intv[0] - (pos - count - 1), -1}; } else { - count += 1 - diff; + count+=1-diff; } } } - return null; //(diff<0) ? (intv[1]-1) : (intv[0]+1); + 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); + Iterator intv = fromShifts2.iterator(); + int iv[],i=0,fs=-1,fe=-1; // containing intervals + while (intv.hasNext() && (fs==-1 || fe==-1)) { + iv = (int[]) intv.next(); + if (iv[0]<=iv[1]) { + if (fs==-1 && startpos>=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 = fromShifts2.iterator(); + i=0; + while (ifs) { + 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 = ranges.iterator(); + i=0; + while (intv.hasNext()) + { + iv = (int[]) intv.next(); + range[i++] = iv[0]; + range[i++] = iv[1]; + intv.remove(); + } + } + return range; + } + /** + * test routine. not incremental. + * @param ml + * @param fromS + * @param fromE + */ public static void testMap(MapList ml, int fromS, int fromE) { for (int from = 1; from <= 25; from++) { - int[] too = ml.shiftFrom(from); - System.out.print("ShiftFrom(" + from + ")=="); - if (too == null) + int[] too=ml.shiftFrom(from); + System.out.print("ShiftFrom("+from+")=="); + if (too==null) { System.out.print("NaN\n"); } else { - System.out.print(too[0] + " % " + too[1]); + System.out.print(too[0]+" % "+too[1]+" ("+too[2]+")"); System.out.print("\t+--+\t"); - int[] toofrom = ml.shiftTo(too[0]); + int[] toofrom=ml.shiftTo(too[0]); if (toofrom != null) { - if (toofrom[0] != from) + if (toofrom[0]!=from) { System.err.println("Mapping not reflexive:" + from + " " + too[0] + - "->" + toofrom[0]); + "->" + toofrom[0]); } System.out.println("ShiftTo(" + too[0] + ")==" + toofrom[0] + " % " + - toofrom[1]); + toofrom[1]+" ("+toofrom[2]+")"); } else { System.out.println("ShiftTo(" + too[0] + ")==" + - "NaN! - not Bijective Mapping!"); + "NaN! - not Bijective Mapping!"); } } } int mmap[][] = ml.makeFromMap(); System.out.println("FromMap : (" + mmap[0][0] + " " + mmap[0][1] + " " + - mmap[0][2] + " " + mmap[0][3] + " "); + 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