package org.seqcode.deepseq.stats;
import org.seqcode.genome.location.Region;
/**
* BackgroundModel: General background for defining thresholds
*
* Model Types:
* Genome-wide = -1
* CurrentRegion = 0
* Local window size = positive integer
*
* @author Shaun Mahony
* @version %I%, %G%
*/
public abstract class BackgroundModel {
protected int modelType; //-1 for genome-wide, 0 for current region, positive integer for local window size
protected double logConfidence;
protected double confThreshold;
protected double totalReads, regionLength, mappableRegion, binWidth;
protected float expectedCount=0;
protected int countThreshold=0;
protected char strand='.';
protected boolean useThisExpt=true;
protected double scaling=1;
public BackgroundModel(int mtype, double lc, double r, double rl, double mr, double bw, char str){this(mtype, lc, r, rl, mr, bw, str, 1, true);}
public BackgroundModel(int mtype, double lc, double r, double rl, double mr, double bw, char str, double sc, boolean ute){
modelType = mtype;
logConfidence=lc;
confThreshold = Math.pow(10,logConfidence);
totalReads=r;
regionLength=rl;
mappableRegion=mr;
binWidth=bw;
strand=str;
scaling = sc;
useThisExpt = ute;
countThreshold = calcCountThreshold();
expectedCount = calcExpectedCount();
}
//Accessors
public char getStrand(){return strand;}
public boolean isGenomeWide(){return modelType==-1 ? true : false;}
public float getExpectedCount(){ return expectedCount;}
public int getThreshold(){return countThreshold;}
//Required
public abstract boolean passesThreshold(int count);
public abstract boolean underThreshold(int count);
protected abstract int calcCountThreshold();
protected abstract float calcExpectedCount();
//Update the threshold (depends on the type of model... local, etc)
public void updateModel(Region currReg, int currOffset, float [] thisExptHitCounts, float [] otherExptHitCounts, float hitCountBinStep){
float [] hitCounts = useThisExpt ? thisExptHitCounts : otherExptHitCounts;
if(hitCounts!=null){
if(modelType==-1){//Genome-wide
if(countThreshold==0){
countThreshold = calcCountThreshold();
expectedCount = calcExpectedCount();
}
}else if(modelType==0){//Current region
float sum=1;//pseudo count
for(int i=0; i<hitCounts.length; i++)
sum+=hitCounts[i];
totalReads = scaling*sum;
regionLength = currReg.getWidth();
mappableRegion=1.0;//Big assumption
countThreshold = calcCountThreshold();
expectedCount = calcExpectedCount();
}else{//Window around current position
int win = modelType;
int istart = currOffset-(win/2)<0 ? 0 :currOffset-(win/2);
int istop = currOffset+(win/2)>=currReg.getWidth() ? currReg.getWidth()-1 :currOffset+(win/2);
int istartbin = (int)(istart/hitCountBinStep);
int istopbin = (int)(istop/hitCountBinStep);
float sum=1;//pseudo count
for(int i=istartbin; i<=istopbin; i++){
sum+=hitCounts[i];
}
totalReads = scaling*sum;
regionLength=istop-istart+1;
//mappableRegion=1.0; //any need for this assumption?
countThreshold = calcCountThreshold();
expectedCount = calcExpectedCount();
}
}
}
}