Initial Commit - works well, but too memory intensive
This commit is contained in:
6
src/main/java/Equations.java
Normal file
6
src/main/java/Equations.java
Normal file
@@ -0,0 +1,6 @@
|
||||
public abstract class Equations {
|
||||
|
||||
public static double pValue(Integer w, Integer w_a, Integer w_b, Integer w_ab) {
|
||||
return 1.0;
|
||||
}
|
||||
}
|
||||
102
src/main/java/Plate.java
Normal file
102
src/main/java/Plate.java
Normal file
@@ -0,0 +1,102 @@
|
||||
import java.sql.Array;
|
||||
import java.util.*;
|
||||
|
||||
public class Plate {
|
||||
private List<List<Integer[]>> wells;
|
||||
private Random rand = new Random();
|
||||
private int size;
|
||||
private double error;
|
||||
|
||||
public Plate (int size, double error) {
|
||||
this.size = size;
|
||||
this.error = error;
|
||||
wells = new ArrayList<>();
|
||||
}
|
||||
|
||||
public void fillWells(List<Integer[]> cells, int[] concentrations, double stdDev) {
|
||||
int numSections = concentrations.length;
|
||||
int section = 0;
|
||||
double m;
|
||||
int n;
|
||||
boolean drop;
|
||||
while (section < numSections){
|
||||
for (int i = 0; i < (size / numSections); i++) {
|
||||
List<Integer[]> well = new ArrayList<>();
|
||||
for (int j = 0; j < concentrations[section]; j++) {
|
||||
do {
|
||||
m = Math.abs(rand.nextGaussian()) * stdDev;
|
||||
} while (m >= cells.size());
|
||||
n = (int) Math.floor(m);
|
||||
Integer[] cellToAdd = cells.get(n).clone();
|
||||
drop = Math.abs(rand.nextDouble()) < error;
|
||||
if (drop) {
|
||||
if (rand.nextBoolean()) {
|
||||
cellToAdd[0] = -1;
|
||||
} else {
|
||||
cellToAdd[1] = -1;
|
||||
}
|
||||
}
|
||||
well.add(cellToAdd);
|
||||
}
|
||||
wells.add(well);
|
||||
}
|
||||
section++;
|
||||
}
|
||||
}
|
||||
|
||||
public Map<Integer, Integer> assayWellsAlpha() {
|
||||
return this.assayWellsAlpha(0, size);
|
||||
}
|
||||
|
||||
public Map<Integer, Integer> assayWellsAlpha(int n) {
|
||||
return this.assayWellsAlpha(n, n+1);
|
||||
}
|
||||
|
||||
public Map<Integer, Integer> assayWellsAlpha(int start, int end) {
|
||||
Map<Integer, Integer> assay = new HashMap<>();
|
||||
for(int i = start; i < end; i++){
|
||||
countAlphas(assay, wells.get(i));
|
||||
}
|
||||
return assay;
|
||||
}
|
||||
|
||||
//given a map, counts distinct alphas in a well
|
||||
private void countAlphas(Map<Integer, Integer> wellMap, List<Integer[]> well){
|
||||
for(Integer[] cell : well) {
|
||||
if(cell[0] != -1){
|
||||
//keys are alphas, value is how many of them have been assayed
|
||||
wellMap.merge(cell[0], 1, (oldValue, newValue) -> oldValue + newValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//assays all wells
|
||||
public Map<Integer, Integer> assayWellsBeta() {
|
||||
return this.assayWellsBeta(0, size);
|
||||
}
|
||||
|
||||
//assays a specific well
|
||||
public Map<Integer, Integer> assayWellsBeta(int n) {
|
||||
return this.assayWellsBeta(n, n+1);
|
||||
}
|
||||
|
||||
//assays a range of wells
|
||||
public Map<Integer, Integer> assayWellsBeta(int start, int end) {
|
||||
Map<Integer, Integer> assay = new HashMap<>();
|
||||
for(int i = start; i < end; i++){
|
||||
countBetas(assay, wells.get(i));
|
||||
}
|
||||
return assay;
|
||||
}
|
||||
|
||||
//given a map, counts distinct betas in a well
|
||||
private void countBetas(Map<Integer, Integer> wellMap, List<Integer[]> well){
|
||||
for(Integer[] cell : well) {
|
||||
if(cell[1] != -1){
|
||||
wellMap.merge(cell[1], 1, (oldValue, newValue) -> oldValue + newValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
231
src/main/java/Simulation.java
Normal file
231
src/main/java/Simulation.java
Normal file
@@ -0,0 +1,231 @@
|
||||
import org.jgrapht.Graph;
|
||||
import org.jgrapht.alg.interfaces.MatchingAlgorithm;
|
||||
import org.jgrapht.alg.matching.MaximumWeightBipartiteMatching;
|
||||
import org.jgrapht.graph.DefaultWeightedEdge;
|
||||
import org.jgrapht.graph.SimpleWeightedGraph;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.MathContext;
|
||||
import java.text.NumberFormat;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.*;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
public class Simulation {
|
||||
private static Integer numDistinctCells = 4_000_000;
|
||||
private static double stdDeviation;
|
||||
private static int numWells = 96;
|
||||
private static int numConcentrations = 1;
|
||||
private static double errorRate = 0.1;
|
||||
private static int[] concentrations = {50, 500, 5000};
|
||||
private static int lowThreshold = 2; //min number of shared wells to attempt pairing
|
||||
private static int highThreshold = 96; //max number of shared wells to attempt pairing
|
||||
|
||||
public static void main(String[] args) {
|
||||
Instant start = Instant.now();
|
||||
|
||||
stdDeviation = Math.sqrt(numDistinctCells.doubleValue());
|
||||
//concentrations = new int[numConcentrations];
|
||||
|
||||
//OUTPUT
|
||||
System.out.println("Generating cells");
|
||||
|
||||
List<Integer> numbers = new ArrayList<>();
|
||||
IntStream.range(1, (2 * numDistinctCells) + 1).forEach(i -> numbers.add(i));
|
||||
Collections.shuffle(numbers);
|
||||
|
||||
//Each cell represented by two numbers from the random permutation
|
||||
//These represent unique alpha and beta peptides
|
||||
List<Integer[]> distinctCells = new ArrayList<>();
|
||||
for(int i = 0; i < numbers.size() - 1; i = i + 2) {
|
||||
Integer tmp1 = numbers.get(i);
|
||||
Integer tmp2 = numbers.get(i+1);
|
||||
Integer[] tmp = {tmp1, tmp2};
|
||||
distinctCells.add(tmp);
|
||||
}
|
||||
|
||||
//OUTPUT
|
||||
System.out.println("Cells generated");
|
||||
System.out.println("Filling wells");
|
||||
|
||||
//HashMap keyed to Alphas, values Betas
|
||||
Map<Integer, Integer> distCellsMapAlphaKey = new HashMap<>();
|
||||
for (Integer[] cell : distinctCells) {
|
||||
distCellsMapAlphaKey.put(cell[0], cell[1]);
|
||||
}
|
||||
|
||||
//HashMap keyed to Betas, values Alphas
|
||||
Map<Integer, Integer> distCellsMapBetaKey = new HashMap<>();
|
||||
for (Integer[] cell : distinctCells) {
|
||||
distCellsMapBetaKey.put(cell[1], cell[0]);
|
||||
}
|
||||
|
||||
Plate samplePlate = new Plate(numWells, errorRate);
|
||||
samplePlate.fillWells(distinctCells, concentrations, stdDeviation);
|
||||
|
||||
//OUTPUT
|
||||
System.out.println("Wells filled");
|
||||
System.out.println("Making maps");
|
||||
|
||||
//All alphas on plate, with
|
||||
Map<Integer, Integer> allAlphas = samplePlate.assayWellsAlpha();
|
||||
Map<Integer, Integer> allBetas = samplePlate.assayWellsBeta();
|
||||
int alphaCount = allAlphas.size();
|
||||
int betaCount = allBetas.size();
|
||||
|
||||
//keys are sequential integer vertices, values are alphas
|
||||
Map<String, Integer> plateVtoAMap = getVertexToPeptideMap(allAlphas, "A");
|
||||
//keys are sequential integers vertices, values are betas
|
||||
Map<String, Integer> plateVtoBMap = getVertexToPeptideMap(allBetas, "B");
|
||||
//keys are alphas, values are sequential integer vertices from previous map
|
||||
Map<Integer, String> plateAtoVMap = invertVertexMap(plateVtoAMap);
|
||||
//keys are betas, values are sequential integer vertices from previous map
|
||||
Map<Integer, String> plateBtoVMap = invertVertexMap(plateVtoBMap);
|
||||
|
||||
//OUTPUT
|
||||
System.out.println("Maps made");
|
||||
System.out.println("Creating Graph");
|
||||
|
||||
//construct graph
|
||||
SimpleWeightedGraph<String, DefaultWeightedEdge> graph = new SimpleWeightedGraph<String, DefaultWeightedEdge>(DefaultWeightedEdge.class);
|
||||
//add vertices
|
||||
for(String v: plateVtoAMap.keySet()) {
|
||||
graph.addVertex(v);
|
||||
}
|
||||
for(String v: plateVtoBMap.keySet()) {
|
||||
graph.addVertex(v);
|
||||
}
|
||||
//add edges, where weights are number of wells the peptides share in common.
|
||||
//If this is too slow, can make a 2d array and use the SimpleWeightedGraphMatrixGenerator class
|
||||
Map<Integer, Integer> wellNAlphas = null;
|
||||
Map<Integer, Integer> wellNBetas = null;
|
||||
//Count how many wells each alpha appears in
|
||||
Map<Integer, Integer> alphaWellCounts = new HashMap<>();
|
||||
//count how many wells each beta appears in
|
||||
Map<Integer, Integer> betaWellCounts = new HashMap<>();
|
||||
for (int n = 0; n < numWells; n++) {
|
||||
wellNAlphas = samplePlate.assayWellsAlpha(n);
|
||||
for(Integer a: wellNAlphas.keySet()){
|
||||
alphaWellCounts.merge(a, 1, (oldValue, newValue) -> oldValue + newValue);
|
||||
}
|
||||
wellNBetas = samplePlate.assayWellsBeta(n);
|
||||
for(Integer b: wellNBetas.keySet()){
|
||||
betaWellCounts.merge(b, 1, (oldValue, newValue) -> oldValue + newValue);
|
||||
}
|
||||
for(Integer i: wellNAlphas.keySet()) {
|
||||
for(Integer j: wellNBetas.keySet()){
|
||||
addEdgeOrWeight(graph, plateAtoVMap.get(i), plateBtoVMap.get(j));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//OUTPUT
|
||||
System.out.println("Graph created");
|
||||
System.out.println("Finding maximum weighted matching");
|
||||
|
||||
MaximumWeightBipartiteMatching maxWeightMatching = new MaximumWeightBipartiteMatching(graph, plateVtoAMap.keySet(), plateVtoBMap.keySet());
|
||||
MatchingAlgorithm.Matching<String, DefaultWeightedEdge> graphMatching = maxWeightMatching.getMatching();
|
||||
|
||||
Instant stop = Instant.now();
|
||||
|
||||
//OUTPUT
|
||||
System.out.println("Matching completed");
|
||||
|
||||
|
||||
Iterator<DefaultWeightedEdge> weightIter = graphMatching.iterator();
|
||||
DefaultWeightedEdge e = null;
|
||||
int trueCount = 0;
|
||||
int falseCount = 0;
|
||||
boolean check = false;
|
||||
while(weightIter.hasNext()) {
|
||||
e = weightIter.next();
|
||||
if(graph.getEdgeWeight(e) <= 2.0) {
|
||||
continue;
|
||||
}
|
||||
String source = graph.getEdgeSource(e);
|
||||
String target = graph.getEdgeTarget(e);
|
||||
//Need map of each peptide and number of wells it appears in.
|
||||
check =printData(graph.getEdgeWeight(e), source, alphaWellCounts.get(plateVtoAMap.get(source)), target, betaWellCounts.get(plateVtoBMap.get(target)), distCellsMapAlphaKey, plateVtoAMap, plateVtoBMap);
|
||||
if(check) {
|
||||
trueCount++;
|
||||
}
|
||||
else {
|
||||
falseCount++;
|
||||
}
|
||||
}
|
||||
|
||||
//RESULTS SUMMARY
|
||||
NumberFormat nf = NumberFormat.getInstance(Locale.US);
|
||||
System.out.println("");
|
||||
System.out.println("Distinct cell population: " + nf.format(numDistinctCells));
|
||||
System.out.print("Sample plate: " + numWells +" wells, ");
|
||||
System.out.print("divided into " + concentrations.length + " sections of ");
|
||||
System.out.println(Arrays.toString(concentrations) + " cells per well.");
|
||||
System.out.print("Attempted to match alpha/beta overlaps of at least " + lowThreshold + " wells ");
|
||||
System.out.println("and no more than " + highThreshold + " wells.");
|
||||
System.out.println(nf.format(alphaCount) + " alpha peptides found");
|
||||
System.out.println(nf.format(betaCount) + " beta peptides found");
|
||||
MathContext mc = new MathContext(3);
|
||||
int min = alphaCount > betaCount ? betaCount : alphaCount;
|
||||
double attemptRate = (double) (trueCount + falseCount) / min;
|
||||
BigDecimal attR = new BigDecimal(attemptRate, mc);
|
||||
System.out.println("Pairing attempt rate: " + attR);
|
||||
System.out.println("Correct pairings: " + nf.format(trueCount));
|
||||
System.out.println("Incorrect pairings: " + nf.format(falseCount));
|
||||
double experimentalError = (double) falseCount / (trueCount + falseCount);
|
||||
BigDecimal expErr = new BigDecimal(experimentalError, mc);
|
||||
System.out.println("Pairing error rate: " + expErr);
|
||||
Duration time = Duration.between(start, stop);
|
||||
System.out.println("Simulation time: " + nf.format(time.toSeconds()) + " seconds");
|
||||
System.out.println("");
|
||||
|
||||
|
||||
}
|
||||
|
||||
private static Map<String, Integer> getVertexToPeptideMap(Map<Integer, Integer> peptides, String prefix) {
|
||||
Map<String, Integer> map = new LinkedHashMap<>();
|
||||
Integer index = 0;
|
||||
for (Integer k: peptides.keySet()) {
|
||||
map.put(prefix + index, k);
|
||||
index++;
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
private static Map<Integer, String> invertVertexMap(Map<String, Integer> map) {
|
||||
Map<Integer, String> inverse = new HashMap<>();
|
||||
for(String k: map.keySet()) {
|
||||
inverse.put(map.get(k), k);
|
||||
}
|
||||
return inverse;
|
||||
}
|
||||
|
||||
private static void addEdgeOrWeight(Graph g, String v1, String v2) {
|
||||
if (g.containsEdge(v1, v2)) {
|
||||
g.setEdgeWeight(v1, v2, g.getEdgeWeight(g.getEdge(v1, v2)) + 1.0);
|
||||
}
|
||||
else {
|
||||
g.addEdge(v1, v2);
|
||||
}
|
||||
//System.out.println("added!");
|
||||
}
|
||||
|
||||
private static boolean printData (Double edgeWeight, String source, Integer sourceCount, String target, Integer targetCount, Map<Integer,Integer> AtoBMap, Map<String,Integer> VtoAMap, Map<String, Integer> VtoBMap) {
|
||||
//placeholder for real calculations
|
||||
int trueCount = 0;
|
||||
int falseCount = 0;
|
||||
System.out.println("Alpha peptide " + source + " present in " + sourceCount + " wells");
|
||||
System.out.println("Beta peptide " + target + " present in " + targetCount + " wells");
|
||||
System.out.println("Both alpha and beta present in " + edgeWeight + " wells");
|
||||
if(VtoBMap.get(target).equals(AtoBMap.get(VtoAMap.get(source)))){
|
||||
System.out.println("True");
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
System.out.println("False");
|
||||
System.out.println("The real pair is " + source + " and " + AtoBMap.get(VtoAMap.get(source)));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user