001 package calhoun.analysis.crf.io;
002
003 import java.util.Collection;
004
005 import org.apache.commons.logging.Log;
006 import org.apache.commons.logging.LogFactory;
007
008 import calhoun.util.Assert;
009 import calhoun.util.RangeMap;
010
011 /** an input sequence made up of intervals of constant valued features. Each position is represented
012 * by an {@link IntervalPosition} object.
013 */
014 public class IntervalInputSequence implements InputSequence<IntervalInputSequence.IntervalPosition>{
015 @SuppressWarnings("unused")
016 private static final Log log = LogFactory.getLog(IntervalInputSequence.class);
017
018 RangeMap rmplus,rmminus;
019 String inputName;
020 int inputLength;
021
022 /** constructs an input sequence from the necessary data
023 * @param rmplus range map of values on the positive strand
024 * @param rmminus range map of values on the negative strand
025 * @param inputName name of the input sequence
026 * @param inputLength length of the input sequence. Requires since the intervals may not cover the whole sequence.
027 */
028 public IntervalInputSequence(RangeMap rmplus, RangeMap rmminus, String inputName, int inputLength) {
029 this.rmplus = rmplus;
030 this.rmminus = rmminus;
031 this.inputName = inputName;
032 this.inputLength = inputLength;
033 }
034
035 public IntervalPosition getX(int ix) {
036 IntervalPosition ret = new IntervalPosition(ix);
037 return ret;
038 }
039
040 public int length() {
041 return inputLength;
042 }
043
044 public IntervalInputSequence subSequence(int start, int end) { // 1-based inclusive
045 Assert.a(end >= start);
046 Assert.a(end <= inputLength);
047 Assert.a(start >= 1);
048
049 RangeMap newRmplus = shiftedSubRangeMap(rmplus ,start,end);
050 RangeMap newRmminus = shiftedSubRangeMap(rmminus,start,end);
051
052 return new IntervalInputSequence(newRmplus,newRmminus,inputName,end-start+1);
053 }
054
055 public InputSequence getComponent(String name) {
056 throw new UnsupportedOperationException();
057 }
058
059 public Collection<String> listComponents() {
060 throw new UnsupportedOperationException();
061 }
062
063 private RangeMap shiftedSubRangeMap(RangeMap rm, int start, int end) {
064 Object[] rmplusList = rm.find(start-1,end-1).toArray();
065 RangeMap newrm = new RangeMap();
066 for (int i=0; i<rmplusList.length; i++) {
067 IntervalRangeMapValue irmv = (IntervalRangeMapValue) rmplusList[i];
068 IntervalRangeMapValue newirmv = new IntervalRangeMapValue(irmv.start-start+1, irmv.end-start+1, irmv.value);
069 rm.add(newirmv.start,newirmv.end, newirmv);
070 }
071
072 return newrm;
073 }
074
075 /** provides interval based queries for a particular position in the input sequence for an IntervalInputSequence.
076 */
077 public class IntervalPosition {
078 int pos;
079
080 /** creates an IntervalPosition object for this sequence at this position.
081 * @param pos the position on the input sequence */
082 public IntervalPosition(int pos) {
083 this.pos = pos;
084 }
085
086 /** returns true if an input interval exists on the positive strand at this position. */
087 public boolean queryPlus() {
088 return (rmplus.find(pos,pos+1).size()>0);
089 }
090
091 /** returns true if an input interval exists on the negative strand at this position. */
092 public boolean queryMinus() {
093 return (rmminus.find(pos,pos+1).size()>0);
094 }
095 }
096
097 static public class IntervalRangeMapValue {
098 public int start;
099 public int end;
100 public double value;
101
102 public IntervalRangeMapValue(int start, int end, double value) {
103 this.start = start;
104 this.end = end;
105 this.value = value;
106 }
107
108 public void insertIntoRangeMap(RangeMap RM) {
109 RM.add(start,end,this);
110 }
111
112 public String toStringStrand(String strand) {
113 String ret = "(" + start + "," + end + "," + strand + "," + value + ")";
114 return ret;
115 }
116
117 }
118 }