View Javadoc

1   /*--------------------------------------------------------------------------
2    *  Copyright 2009 utgenome.org
3    *
4    *  Licensed under the Apache License, Version 2.0 (the "License");
5    *  you may not use this file except in compliance with the License.
6    *  You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *  Unless required by applicable law or agreed to in writing, software
11   *  distributed under the License is distributed on an "AS IS" BASIS,
12   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *  See the License for the specific language governing permissions and
14   *  limitations under the License.
15   *--------------------------------------------------------------------------*/
16  //--------------------------------------
17  // utgb-core Project
18  //
19  // Interval.java
20  // Since: 2010/05/24
21  //
22  // $URL$ 
23  // $Author$
24  //--------------------------------------
25  package org.utgenome.gwt.utgb.client.bio;
26  
27  import java.io.Serializable;
28  
29  /**
30   * An interval in a genome sequence.
31   * 
32   * @author leo
33   * 
34   */
35  public class Interval implements OnGenome, Comparable<Interval>, Serializable {
36  
37  	/**
38  	 * 
39  	 */
40  	private static final long serialVersionUID = 1L;
41  
42  	int start = -1; // 1-origin (inclusive, -1 means undefined value)
43  	int end = -1; // 1-origin (exclusive, -1 means undefined value)
44  
45  	public Interval() {
46  	}
47  
48  	public Interval(int start, int end) {
49  		this.start = start;
50  		this.end = end;
51  		correctInterval();
52  	}
53  
54  	public Interval(Interval other) {
55  		this(other.start, other.end);
56  	}
57  
58  	public String getName() {
59  		return "[" + start + ", " + end + ")";
60  	}
61  
62  	public void adjustToOneOrigin() {
63  		if (start != -1)
64  			start += 1;
65  		if (end != -1)
66  			end += 1;
67  	}
68  
69  	public boolean isSense() {
70  		return true;
71  	}
72  
73  	public boolean isAntiSense() {
74  		return false;
75  	}
76  
77  	public String getColor() {
78  		return null;
79  	}
80  
81  	/**
82  	 * Get the start position of the locus. (start <= end)
83  	 * 
84  	 * @return the start position
85  	 */
86  	public int getStart() {
87  		return start;
88  	}
89  
90  	public void setStart(int start) {
91  		this.start = start;
92  		correctInterval();
93  	}
94  
95  	public void atomicSetStartAndEnd(int start, int end) {
96  		this.start = start;
97  		this.end = end;
98  		correctInterval();
99  	}
100 
101 	protected void correctInterval() {
102 		// do not swap start and end when one of them is undefined
103 		if (start == -1 || end == -1)
104 			return;
105 
106 		if (start > end) {
107 			int tmp = start;
108 			start = end;
109 			end = tmp;
110 		}
111 	}
112 
113 	/**
114 	 * Get the end position of the locus (start <= end)
115 	 * 
116 	 * @return the end position
117 	 */
118 	public int getEnd() {
119 		return end;
120 	}
121 
122 	public void setEnd(int end) {
123 		this.end = end;
124 		correctInterval();
125 	}
126 
127 	public int length() {
128 		// when [start:1, end:4), its length = 3
129 		return getEnd() - getStart();
130 	}
131 
132 	public boolean hasOverlap(Interval other) {
133 		int s1 = getStart();
134 		int e1 = getEnd();
135 		int s2 = other.getStart();
136 		int e2 = other.getEnd();
137 
138 		return s1 <= e2 && s2 <= e1;
139 	}
140 
141 	public boolean intersectsWith(Interval other) {
142 		if (start <= other.start)
143 			return other.start <= end;
144 		else
145 			return start <= other.end;
146 	}
147 
148 	/**
149 	 * Return the intersected interval with the other
150 	 * 
151 	 * @param other
152 	 * @return
153 	 */
154 	public Interval intersect(Interval other) {
155 		if (!this.hasOverlap(other))
156 			return null;
157 
158 		int overlapStart = this.getStart() < other.getStart() ? other.getStart() : this.getStart();
159 		int overlapEnd = this.getEnd() < other.getEnd() ? this.getEnd() : other.getEnd();
160 
161 		return new Interval(overlapStart, overlapEnd);
162 	}
163 
164 	public boolean contains(int pos) {
165 		return (start <= pos) && (pos < end);
166 	}
167 
168 	public boolean contains(Interval other) {
169 		return (start <= other.start) && (other.end <= end);
170 	}
171 
172 	public boolean precedes(Interval other) {
173 		return this.end < other.start;
174 	}
175 
176 	public boolean follows(Interval other) {
177 		return other.end <= this.start;
178 	}
179 
180 	public void accept(OnGenomeDataVisitor visitor) {
181 		visitor.visitInterval(this);
182 	}
183 
184 	public int compareTo(Interval other) {
185 		long diff = this.getStart() - other.getStart();
186 		if (diff == 0) {
187 			// Comparing hash values is necessary for the same range intervals but might have different parameter values.
188 			return this.hashCode() - other.hashCode();
189 		}
190 		else
191 			return diff < 0 ? -1 : 1;
192 	}
193 
194 	public String toJSONArray() {
195 		return "[" + start + "," + end + "]";
196 	}
197 
198 	@Override
199 	public String toString() {
200 		return "(" + start + ", " + end + ")";
201 	}
202 
203 }