Files
BiGpairSEQ/src/main/java/Plate.java
2022-02-27 15:54:47 -06:00

185 lines
6.2 KiB
Java

/*
TODO: Implement exponential distribution using inversion method - DONE
TODO: Implement discrete frequency distributions using Vose's Alias Method
*/
import java.util.*;
public class Plate {
private CellSample cells;
private String sourceFile;
private String filename;
private List<List<Integer[]>> wells;
private final Random rand = BiGpairSEQ.getRand();
private int size;
private double error;
private Integer[] populations;
private double stdDev;
private double lambda;
boolean exponential = false;
public Plate(CellSample cells, String cellFilename, int numWells, Integer[] populations,
double dropoutRate, double stdDev_or_lambda, boolean exponential){
this.cells = cells;
this.sourceFile = cellFilename;
this.size = numWells;
this.wells = new ArrayList<>();
this.error = dropoutRate;
this.populations = populations;
this.exponential = exponential;
if (this.exponential) {
this.lambda = stdDev_or_lambda;
fillWellsExponential(cells.getCells(), this.lambda);
}
else {
this.stdDev = stdDev_or_lambda;
fillWells(cells.getCells(), this.stdDev);
}
}
public Plate(int size, double error, Integer[] populations) {
this.size = size;
this.error = error;
this.populations = populations;
wells = new ArrayList<>();
}
//constructor for returning a Plate from a PlateFileReader
public Plate(String filename, List<List<Integer[]>> wells) {
this.filename = filename;
this.wells = wells;
this.size = wells.size();
List<Integer> concentrations = new ArrayList<>();
for (List<Integer[]> w: wells) {
if(!concentrations.contains(w.size())){
concentrations.add(w.size());
}
}
this.populations = new Integer[concentrations.size()];
for (int i = 0; i < this.populations.length; i++) {
this.populations[i] = concentrations.get(i);
}
}
private void fillWellsExponential(List<Integer[]> cells, double lambda){
this.lambda = lambda;
exponential = true;
int numSections = populations.length;
int section = 0;
double m;
int n;
while (section < numSections){
for (int i = 0; i < (size / numSections); i++) {
List<Integer[]> well = new ArrayList<>();
for (int j = 0; j < populations[section]; j++) {
do {
//inverse transform sampling: for random number u in [0,1), x = log(1-u) / (-lambda)
m = (Math.log10((1 - rand.nextDouble()))/(-lambda)) * Math.sqrt(cells.size());
} while (m >= cells.size() || m < 0);
n = (int) Math.floor(m);
Integer[] cellToAdd = cells.get(n).clone();
for(int k = 0; k < cellToAdd.length; k++){
if(Math.abs(rand.nextDouble()) < error){//error applied to each seqeunce
cellToAdd[k] = -1;
}
}
well.add(cellToAdd);
}
wells.add(well);
}
section++;
}
}
private void fillWells( List<Integer[]> cells, double stdDev) {
this.stdDev = stdDev;
int numSections = populations.length;
int section = 0;
double m;
int n;
while (section < numSections){
for (int i = 0; i < (size / numSections); i++) {
List<Integer[]> well = new ArrayList<>();
for (int j = 0; j < populations[section]; j++) {
do {
m = (rand.nextGaussian() * stdDev) + (cells.size() / 2);
} while (m >= cells.size() || m < 0);
n = (int) Math.floor(m);
Integer[] cellToAdd = cells.get(n).clone();
for(int k = 0; k < cellToAdd.length; k++){
if(Math.abs(rand.nextDouble()) < error){//error applied to each sequence
cellToAdd[k] = -1;
}
}
well.add(cellToAdd);
}
wells.add(well);
}
section++;
}
}
public Integer[] getPopulations(){
return populations;
}
public int getSize(){
return size;
}
public double getStdDev() {
return stdDev;
}
public boolean isExponential(){return exponential;}
public double getLambda(){return lambda;}
public double getError() {
return error;
}
public List<List<Integer[]>> getWells() {
return wells;
}
//returns a map of the counts of the sequence at cell index sIndex, in all wells
public Map<Integer, Integer> assayWellsSequenceS(int... sIndices){
return this.assayWellsSequenceS(0, size, sIndices);
}
//returns a map of the counts of the sequence at cell index sIndex, in a specific well
public Map<Integer, Integer> assayWellsSequenceS(int n, int... sIndices) { return this.assayWellsSequenceS(n, n+1, sIndices);}
//returns a map of the counts of the sequence at cell index sIndex, in a range of wells
public Map<Integer, Integer> assayWellsSequenceS(int start, int end, int... sIndices) {
Map<Integer,Integer> assay = new HashMap<>();
for(int pIndex: sIndices){
for(int i = start; i < end; i++){
countSequences(assay, wells.get(i), pIndex);
}
}
return assay;
}
//For the sequences at cell indices sIndices, counts number of unique sequences in the given well into the given map
private void countSequences(Map<Integer, Integer> wellMap, List<Integer[]> well, int... sIndices) {
for(Integer[] cell : well) {
for(int sIndex: sIndices){
if(cell[sIndex] != -1){
wellMap.merge(cell[sIndex], 1, (oldValue, newValue) -> oldValue + newValue);
}
}
}
}
public String getSourceFileName() {
return sourceFile;
}
public String getFilename() { return filename; }
}