/* 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 String sourceFile; private List> 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(int size, double error, Integer[] populations) { this.size = size; this.error = error; this.populations = populations; wells = new ArrayList<>(); } public Plate(String sourceFileName, List> wells) { this.sourceFile = sourceFileName; this.wells = wells; this.size = wells.size(); List concentrations = new ArrayList<>(); for (List 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); } } public void fillWellsExponential(String sourceFileName, List cells, double lambda){ this.lambda = lambda; exponential = true; sourceFile = sourceFileName; int numSections = populations.length; int section = 0; double m; int n; while (section < numSections){ for (int i = 0; i < (size / numSections); i++) { List 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++; } } public void fillWells(String sourceFileName, List cells, double stdDev) { this.stdDev = stdDev; sourceFile = sourceFileName; int numSections = populations.length; int section = 0; double m; int n; while (section < numSections){ for (int i = 0; i < (size / numSections); i++) { List 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> getWells() { return wells; } //returns a map of the counts of the sequence at cell index sIndex, in all wells public Map 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 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 assayWellsSequenceS(int start, int end, int... sIndices) { Map 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 wellMap, List 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; } }