/*
* The MIT License (MIT)
*
* Copyright (c) 2007-2015 Broad Institute
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package org.broad.igv.bbfile;
import org.apache.log4j.Logger;
/**
* Created by IntelliJ IDEA.
* User: martind
* Date: Jan 22, 2010
* Time: 3:37:38 PM
* private int mStartChromID; // starting chromosome in item
* To change this template use File | Settings | File Templates.
*/
/*
* Container class for R+ Tree bounding rectangle regions
* */
public class RPChromosomeRegion {
private static Logger log = Logger.getLogger(RPChromosomeRegion.class);
private int startChromID; // starting mChromosome in item
private int startBase; // starting base pair in item
private int endChromID; // ending mChromosome in item
private int endBase; // ending base pair in item
/*
* Construct region from a specification.
* */
public RPChromosomeRegion(int startChromID, int startBase,
int endChromID, int endBase) {
this.startChromID = startChromID;
this.startBase = startBase;
this.endChromID = endChromID;
this.endBase = endBase;
}
/*
* Construct region from an existing region.
* */
public RPChromosomeRegion(RPChromosomeRegion region) {
startChromID = region.startChromID;
startBase = region.startBase;
endChromID = region.endChromID;
endBase = region.endBase;
}
/*
* Null region constructor for setting region members.
**/
public RPChromosomeRegion() {
// members auto-inited
}
public int getStartChromID() {
return startChromID;
}
public int getStartBase() {
return startBase;
}
public int getEndChromID() {
return endChromID;
}
public int getEndBase() {
return endBase;
}
public void print() {
log.debug("Chromosome bounds:");
log.debug("StartChromID = " + startChromID);
log.debug("StartBase = " + startBase);
log.debug("EndChromID = " + endChromID);
log.debug("EndBase = " + endBase);
}
/**
* Comparator for mChromosome bounds is used to find relevant intervals and
* rank placement of node items. Returned value indicates relative
* positioning to supplied chromosome test region , and expands on normal
* comparator by indicating partial overlap in the extremes.
* <p/>
* Returns:
* - 2 indicates that this region is completely disjoint below the test region
* -1 indicates this region intersects the test region from below
* 0 indicates that this region is inclusive to the test region
* 1 indicates this region intersects the test region from above
* 2 indicates that this region is completely disjoint above the test region
* <p/>
* Note: additional tests can be applied to determine intersection from above
* or below the test region and disjoint above or below the test region cases.
*/
public int compareRegions(RPChromosomeRegion testRegion) {
return compareRegions(testRegion.startChromID, testRegion.startBase, testRegion.endChromID, testRegion.endBase);
}
public int compareRegions(int testRegionStartChromID, int testRegionStartBase, int testRegionEndChromID, int testRegionEndBase) {
// test if this region is contained by (i.e. subset of) testRegion region
if (containedIn(testRegionStartChromID, testRegionStartBase, testRegionEndChromID, testRegionEndBase))
return 0;
// test if testRegion region is disjoint from above or below
else if (disjointBelow(testRegionStartChromID, testRegionStartBase))
return -2;
else if (disjointAbove(testRegionEndChromID, testRegionEndBase))
return 2;
// Otherwise this region must intersect
else if (this.intersectsBelow(testRegionStartChromID, testRegionStartBase))
return -1;
else if (this.intersectsAbove(testRegionEndChromID, testRegionEndBase))
return 1;
// unexpected condition is unknown
return 3;
}
/**
* Method checks if test region contains this region;
* (i.e this region is subset oftest region).
* <p/>
* Parameters:
* testRegion - chromosome selection region
* <p/>
* Returns:
* This region is contained in the test region: true or false
*/
private boolean containedIn(int testRegionStartChromID, int testRegionStartBase, int testRegionEndChromID, int testRegionEndBase) {
if (startChromID > testRegionStartChromID ||
(startChromID == testRegionStartChromID && startBase >= testRegionStartBase)) {
if (endChromID < testRegionEndChromID ||
(endChromID == testRegionEndChromID && endBase <= testRegionEndBase))
return true;
else
return false;
} else
return false;
}
/**
* Method checks if this region intersects test region from below
* <p/>
* Note: To be true, this region must have some part outside the test region
* <p/>
* Parameters:
* testRegion - chromosome selection region
* <p/>
* Returns:
* This region intersects the test region from below: true or false
*/
private boolean intersectsBelow(int testRegionStartChromID, int testRegionStartBase) {
// Only need to test if some part of this region is below and some within test region.
if (startChromID < testRegionStartChromID ||
(startChromID == testRegionStartChromID && startBase < testRegionStartBase)) {
if (endChromID > testRegionStartChromID ||
(endChromID == testRegionStartChromID && endBase > testRegionStartBase))
return true;
else
return false;
} else
return false;
}
/**
* Method checks if this region intersects test region from above.
* <p/>
* Note: To be true, this region must have some part outside the test region
* <p/>
* Parameters:
* testRegion - chromosome selection region
* <p/>
* Returns:
* This region intersects the test region from above: true or false
*/
private boolean intersectsAbove(int testRegionEndChromID, int testRegionEndBase) {
// Only need to test if some part of this region is above and some within test region.
if (endChromID > testRegionEndChromID ||
(endChromID == testRegionEndChromID && endBase > testRegionEndBase)) {
if (startChromID < testRegionEndChromID ||
(startChromID == testRegionEndChromID && startBase < testRegionEndBase))
return true;
else
return false;
} else
return false;
}
/**
* Method checks if this region is completely below test region.
* <p/>
* Parameters:
* testRegion - chromosome selection region
* <p/>
* Returns:
* This region is disjoint below the test region: true or false
*/
private boolean disjointBelow(int testRegionStartChromID, int testRegionStartBase) {
if (endChromID < testRegionStartChromID ||
endChromID == testRegionStartChromID && endBase <= testRegionStartBase)
return true;
else
return false;
}
/**
* Method checks if this region region is completely above test region.
* <p/>
* Parameters:
* testRegion - chromosome selection region
* <p/>
* Returns:
* This region is disjoint above the test region: true or false
*/
private boolean disjointAbove(int testRegionEndChromID, int testRegionEndBase) {
if (startChromID > testRegionEndChromID ||
startChromID == testRegionEndChromID && startBase >= testRegionEndBase)
return true;
else
return false;
}
/**
* Method computes the extremes between this region and the test region
* <p/>
* Parameters:
* testRegion - chromosome region to compare against this region
* <p/>
* Returns:
* new chromosome region of extremes
*/
public RPChromosomeRegion getExtremes(RPChromosomeRegion testRegion) {
RPChromosomeRegion newRegion = new RPChromosomeRegion(this);
// update node bounds
if (testRegion.startChromID < newRegion.startChromID ||
(testRegion.startChromID == newRegion.startChromID &&
testRegion.startBase < newRegion.startBase)) {
newRegion.startChromID = testRegion.startChromID;
newRegion.startBase = testRegion.startBase;
}
if (testRegion.endChromID > newRegion.endChromID ||
(testRegion.endChromID == newRegion.endChromID &&
testRegion.endBase > newRegion.endBase)) {
newRegion.endChromID = testRegion.endChromID;
newRegion.endBase = testRegion.endBase;
}
return newRegion;
}
}