/* * This file is part of the Vamsas Client version 0.1. * Copyright 2009 by Jim Procter, Iain Milne, Pierre Marguerite, * Andrew Waterhouse and Dominik Lindner. * * Earlier versions have also been incorporated into Jalview version 2.4 * since 2008, and TOPALi version 2 since 2007. * * The Vamsas Client is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * The Vamsas Client 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the Vamsas Client. If not, see . */ package uk.ac.vamsas.objects.utils; /* * This code was originated from * 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 */ import java.util.Vector; 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; } /* * public Mapping(SequenceI to, MapList map) { this(map); this.to = to; } */ /** * create a new mapping from * * (in Jalview) param to was the destination sequence being mapped * * @param local * int[] {start,end,start,end} series on associated sequence * @param mapped * 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[] local, int[] mapped, int i, int j) { this(new MapList(local, mapped, i, j)); } /** * create a duplicate (and independent) mapping object with the same reference * to any SequenceI being mapped to. * * @param map2 */ public Mapping(Mapping map2) { if (map2 != this && map2 != null) { if (map2.map != null) { map = new MapList(map2.map); } } } /** * @return the map */ public MapList getMap() { return map; } /** * @param map * the map to set */ public void setMap(MapList map) { this.map = map; } /** * Equals that compares both the to references and MapList mappings. * * @param other * @return */ 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; } /** * gets boundary in direction of mapping * * @param position * in mapped reference frame * @return int{start, end} positions in associated sequence (in direction of * mapped word) */ public int[] getWord(int mpos) { if (map != null) { return map.getToWord(mpos); } 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 (local) sequence's * reference frame * * @param f * @return int[] { start1, end1, ... starti, endi } for the corresponding * interval in local reference frame */ public int[] locateFeature(int begin, int end) { if (true) { // f.getBegin()!=f.getEnd()) { if (map != null) { int[] frange = map.locateInFrom(begin, end); // f.getBegin(), // f.getEnd()); /* * left in as an example as to how this is used in Jalview * SequenceFeature[] vf = new SequenceFeature[frange.length / 2]; for * (int i = 0, v = 0; i < frange.length; i += 2, v++) { vf[v] = new * SequenceFeature(f); vf[v].setBegin(frange[i]); vf[v].setEnd(frange[i * + 1]); if (frange.length > 2) vf[v].setDescription(f.getDescription() * + "\nPart " + v); } */ return frange; } } // give up and just return the interval unchanged - this might not be the // correct behaviour return new int[] { begin, end }; } /** * 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 int[] { from_i, to_i for i=1 to n contiguous regions in the * associated sequence} */ public int[] locateRange(int from, int to) { if (map != null) { if (from <= to) { from = (map.getToLowest() < from) ? from : map.getToLowest(); to = (map.getToHighest() > to) ? to : map.getToHighest(); if (from > to) return null; } else { from = (map.getToHighest() > from) ? from : map.getToHighest(); to = (map.getToLowest() < to) ? to : map.getToLowest(); if (from < to) return null; } return map.locateInFrom(from, to); } return new int[] { from, to }; } /** * return a series of mapped contigs mapped from a range on the associated * sequence * * @param from * @param to * @return */ public int[] locateMappedRange(int from, int to) { if (map != null) { if (from <= to) { from = (map.getFromLowest() < from) ? from : map.getFromLowest(); to = (map.getFromHighest() > to) ? to : map.getFromHighest(); if (from > to) return null; } else { from = (map.getFromHighest() > from) ? from : map.getFromHighest(); to = (map.getFromLowest() < to) ? to : map.getFromLowest(); if (from < to) return null; } return map.locateInTo(from, to); } return new int[] { from, to }; } /** * return a new mapping object with a maplist modifed to only map the visible * regions defined by viscontigs. * * @param viscontigs * @return */ public Mapping intersectVisContigs(int[] viscontigs) { Mapping copy = new Mapping(this); if (map != null) { Vector toRange = new Vector(); Vector fromRange = new Vector(); for (int vc = 0; vc < viscontigs.length; vc += 2) { // find a mapped range in this visible region int[] mpr = locateMappedRange(1 + viscontigs[vc], viscontigs[vc + 1] - 1); if (mpr != null) { for (int m = 0; m < mpr.length; m += 2) { toRange.addElement(new int[] { mpr[m], mpr[m + 1] }); int[] xpos = locateRange(mpr[m], mpr[m + 1]); for (int x = 0; x < xpos.length; x += 2) { fromRange.addElement(new int[] { xpos[x], xpos[x + 1] }); } } } } int[] from = new int[fromRange.size() * 2]; int[] to = new int[toRange.size() * 2]; int[] r; for (int f = 0, fSize = fromRange.size(); f < fSize; f++) { r = (int[]) fromRange.elementAt(f); from[f * 2] = r[0]; from[f * 2 + 1] = r[1]; } for (int f = 0, fSize = toRange.size(); f < fSize; f++) { r = (int[]) toRange.elementAt(f); to[f * 2] = r[0]; to[f * 2 + 1] = r[1]; } copy.setMap(new MapList(from, to, map.getFromRatio(), map.getToRatio())); } return copy; } public static void main(String[] args) { /** * trite test of the intersectVisContigs method for a simple DNA -> Protein * exon map and a range of visContigs */ MapList fk = new MapList(new int[] { 1, 6, 8, 13, 15, 23 }, new int[] { 1, 7 }, 3, 1); Mapping m = new Mapping(fk); Mapping m_1 = m.intersectVisContigs(new int[] { fk.getFromLowest(), fk.getFromHighest() }); Mapping m_2 = m.intersectVisContigs(new int[] { 1, 7, 11, 20 }); System.out.println("" + m_1.map.getFromRanges()); // this test was for debugging purposes only - it should run without // exceptions, but the // integrity of the mapping was checked using an interactive debugger rather // than programmatically. } }