    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    }