16 Commits

11 changed files with 282 additions and 116 deletions

View File

@@ -12,7 +12,7 @@ Unlike pairSEQ, which calculates p-values for every TCR alpha/beta overlap and c
against a null distribution, BiGpairSEQ does not do any statistical calculations against a null distribution, BiGpairSEQ does not do any statistical calculations
directly. directly.
BiGpairSEQ creates a [simple bipartite weighted graph](https://en.wikipedia.org/wiki/Bipartite_graph) representing the sample plate. BiGpairSEQ creates a [weightd bipartite graph](https://en.wikipedia.org/wiki/Bipartite_graph) representing the sample plate.
The distinct TCRA and TCRB sequences form the two sets of vertices. Every TCRA/TCRB pair that share a well The distinct TCRA and TCRB sequences form the two sets of vertices. Every TCRA/TCRB pair that share a well
are connected by an edge, with the edge weight set to the number of wells in which both sequences appear. are connected by an edge, with the edge weight set to the number of wells in which both sequences appear.
(Sequences present in *all* wells are filtered out prior to creating the graph, as there is no signal in their occupancy pattern.) (Sequences present in *all* wells are filtered out prior to creating the graph, as there is no signal in their occupancy pattern.)
@@ -69,16 +69,26 @@ Please select an option:
0) Exit 0) Exit
``` ```
### OUTPUT ### INPUT/OUTPUT
To run the simulation, the program reads and writes 4 kinds of files: To run the simulation, the program reads and writes 4 kinds of files:
* Cell Sample files in CSV format * Cell Sample files in CSV format
* Sample Plate files in CSV format * Sample Plate files in CSV format
* Graph and Data files in binary object serialization format * Graph/Data files in binary object serialization format
* Matching Results files in CSV format * Matching Results files in CSV format
These files are often generated in sequence. To save file I/O time, the most recent instance of each of these four
files either generated or read from disk is cached in program memory. This is especially important for Graph/Data files,
which can be several gigabytes in size. Since some simulations may require running multiple,
differntly-configured BiGpairSEQ matchings on the same graph, keeping the most recent graph cached drastically reduces
execution time.
Subsequent uses of the same data file won't need to be read in again until another file of that type is used or generated.
The program checks whether it needs to update its cached data by comparing filenames as entered by the user. On
encountering a new filename, the program flushes its cache and reads in the new file.
When entering filenames, it is not necessary to include the file extension (.csv or .ser). When reading or When entering filenames, it is not necessary to include the file extension (.csv or .ser). When reading or
writing files, the program will automatically add the correct extension to any filename without one. writing files, the program will automatically add the correct extension to any filename without one.
#### Cell Sample Files #### Cell Sample Files
Cell Sample files consist of any number of distinct "T cells." Every cell contains Cell Sample files consist of any number of distinct "T cells." Every cell contains
@@ -121,7 +131,7 @@ Options when making a Sample Plate file:
* Standard deviation size * Standard deviation size
* Exponential * Exponential
* Lambda value * Lambda value
* (Based on the slope of the graph in Figure 4C of the pairSEQ paper, the distribution of the original experiment was exponential with a lambda of approximately 0.6. (Howie, et al. 2015)) * *(Based on the slope of the graph in Figure 4C of the pairSEQ paper, the distribution of the original experiment was exponential with a lambda of approximately 0.6. (Howie, et al. 2015))*
* Total number of wells on the plate * Total number of wells on the plate
* Number of sections on plate * Number of sections on plate
* Number of T cells per well * Number of T cells per well
@@ -129,7 +139,7 @@ Options when making a Sample Plate file:
* Dropout rate * Dropout rate
Files are in CSV format. There are no header labels. Every row represents a well. Files are in CSV format. There are no header labels. Every row represents a well.
Every column represents an individual cell, containing four sequences, depicted as an array string: Every value represents an individual cell, containing four sequences, depicted as an array string:
`[CDR3A, CDR3B, CDR1A, CDR1B]`. So a representative cell might look like this: `[CDR3A, CDR3B, CDR1A, CDR1B]`. So a representative cell might look like this:
`[525902, 791533, -1, 866282]` `[525902, 791533, -1, 866282]`
@@ -155,14 +165,16 @@ Structure:
--- ---
#### Graph and Data Files #### Graph/Data Files
Graph and Data files are serialized binaries of a Java object containing the weigthed bipartite graph representation of a Graph/Data files are serialized binaries of a Java object containing the weigthed bipartite graph representation of a
Sample Plate, along with the necessary metadata for matching and results output. Making them requires a Cell Sample file Sample Plate, along with the necessary metadata for matching and results output. Making them requires a Cell Sample file
(to construct a list of correct sequence pairs for checking the accuracy of BiGpairSEQ simulations) and a (to construct a list of correct sequence pairs for checking the accuracy of BiGpairSEQ simulations) and a
Sample Plate file (to construct the associated occupancy graph). These files can be several gigabytes in size. Sample Plate file (to construct the associated occupancy graph).
Writing them to a file lets us generate a graph and its metadata once, then use it for multiple different BiGpairSEQ simulations.
Options for creating a Graph and Data file: These files can be several gigabytes in size. Writing them to a file lets us generate a graph and its metadata once,
then use it for multiple different BiGpairSEQ simulations.
Options for creating a Graph/Data file:
* The Cell Sample file to use * The Cell Sample file to use
* The Sample Plate file to use. (This must have been generated from the selected Cell Sample file.) * The Sample Plate file to use. (This must have been generated from the selected Cell Sample file.)
@@ -172,8 +184,8 @@ portable data format may be implemented in the future. The tricky part is encodi
--- ---
#### Matching Results Files #### Matching Results Files
Matching results files consist of the results of a BiGpairSEQ matching simulation. Matching results files consist of the results of a BiGpairSEQ matching simulation. Making them requires a Graph and
Files are in CSV format. Rows are sequence pairings with extra relevant data. Columns are pairing-specific details. Data file. Matching results files are in CSV format. Rows are sequence pairings with extra relevant data. Columns are pairing-specific details.
Metadata about the matching simulation is included as comments. Comments are preceded by `#`. Metadata about the matching simulation is included as comments. Comments are preceded by `#`.
Options when running a BiGpairSEQ simulation of CDR3 alpha/beta matching: Options when running a BiGpairSEQ simulation of CDR3 alpha/beta matching:

View File

@@ -1,6 +1,13 @@
//main class. Only job is to choose which interface to use, and hold graph data in memory import java.util.Random;
//main class. For choosing interface type and caching file data
public class BiGpairSEQ { public class BiGpairSEQ {
private static final Random rand = new Random();
private static CellSample cellSampleInMemory = null;
private static String cellFilename = null;
private static Plate plateInMemory = null;
private static String plateFilename = null;
private static GraphWithMapData graphInMemory = null; private static GraphWithMapData graphInMemory = null;
private static String graphFilename = null; private static String graphFilename = null;
@@ -15,18 +22,64 @@ public class BiGpairSEQ {
} }
} }
public static GraphWithMapData getGraph() { public static Random getRand() {
return rand;
}
public static CellSample getCellSampleInMemory() {
return cellSampleInMemory;
}
public static void setCellSampleInMemory(CellSample cellSampleInMemory) {
BiGpairSEQ.cellSampleInMemory = cellSampleInMemory;
}
public static void clearCellSampleInMemory() {
cellSampleInMemory = null;
System.gc();
}
public static String getCellFilename() {
return cellFilename;
}
public static void setCellFilename(String cellFilename) {
BiGpairSEQ.cellFilename = cellFilename;
}
public static Plate getPlateInMemory() {
return plateInMemory;
}
public static void setPlateInMemory(Plate plateInMemory) {
BiGpairSEQ.plateInMemory = plateInMemory;
}
public static void clearPlateInMemory() {
plateInMemory = null;
System.gc();
}
public static String getPlateFilename() {
return plateFilename;
}
public static void setPlateFilename(String plateFilename) {
BiGpairSEQ.plateFilename = plateFilename;
}
public static GraphWithMapData getGraphInMemory() {
return graphInMemory; return graphInMemory;
} }
public static void setGraph(GraphWithMapData g) { public static void setGraphInMemory(GraphWithMapData g) {
if (graphInMemory != null) { if (graphInMemory != null) {
clearGraph(); clearGraphInMemory();
} }
graphInMemory = g; graphInMemory = g;
} }
public static void clearGraph() { public static void clearGraphInMemory() {
graphInMemory = null; graphInMemory = null;
System.gc(); System.gc();
} }

View File

@@ -13,6 +13,7 @@ public class CellFileReader {
private String filename; private String filename;
private List<Integer[]> distinctCells = new ArrayList<>(); private List<Integer[]> distinctCells = new ArrayList<>();
private Integer cdr1Freq;
public CellFileReader(String filename) { public CellFileReader(String filename) {
if(!filename.matches(".*\\.csv")){ if(!filename.matches(".*\\.csv")){
@@ -38,19 +39,37 @@ public class CellFileReader {
cell[3] = Integer.valueOf(record.get("Beta CDR1")); cell[3] = Integer.valueOf(record.get("Beta CDR1"));
distinctCells.add(cell); distinctCells.add(cell);
} }
} catch(IOException ex){ } catch(IOException ex){
System.out.println("cell file " + filename + " not found."); System.out.println("cell file " + filename + " not found.");
System.err.println(ex); System.err.println(ex);
} }
//get CDR1 frequency
ArrayList<Integer> cdr1Alphas = new ArrayList<>();
for (Integer[] cell : distinctCells) {
cdr1Alphas.add(cell[3]);
}
double count = cdr1Alphas.stream().distinct().count();
count = Math.ceil(distinctCells.size() / count);
cdr1Freq = (int) count;
}
public CellSample getCellSample() {
return new CellSample(distinctCells, cdr1Freq);
} }
public String getFilename() { return filename;} public String getFilename() { return filename;}
public List<Integer[]> getCells(){ //Refactor everything that uses this to have access to a Cell Sample and get the cells there instead.
public List<Integer[]> getListOfDistinctCellsDEPRECATED(){
return distinctCells; return distinctCells;
} }
public Integer getCellCount() { public Integer getCellCountDEPRECATED() {
//Refactor everything that uses this to have access to a Cell Sample and get the count there instead.
return distinctCells.size(); return distinctCells.size();
} }
} }

View File

@@ -18,7 +18,7 @@ public class CellSample {
return cdr1Freq; return cdr1Freq;
} }
public Integer population(){ public Integer getCellCount(){
return cells.size(); return cells.size();
} }

View File

@@ -297,7 +297,7 @@ public class CommandLineInterface {
Integer numWells, Integer[] concentrations, Double dropOutRate){ Integer numWells, Integer[] concentrations, Double dropOutRate){
CellFileReader cellReader = new CellFileReader(cellFile); CellFileReader cellReader = new CellFileReader(cellFile);
Plate samplePlate = new Plate(numWells, dropOutRate, concentrations); Plate samplePlate = new Plate(numWells, dropOutRate, concentrations);
samplePlate.fillWellsExponential(cellReader.getFilename(), cellReader.getCells(), lambda); samplePlate.fillWellsExponential(cellReader.getFilename(), cellReader.getListOfDistinctCellsDEPRECATED(), lambda);
PlateFileWriter writer = new PlateFileWriter(filename, samplePlate); PlateFileWriter writer = new PlateFileWriter(filename, samplePlate);
writer.writePlateFile(); writer.writePlateFile();
} }
@@ -305,9 +305,9 @@ public class CommandLineInterface {
private static void makePlatePoisson(String cellFile, String filename, Integer numWells, private static void makePlatePoisson(String cellFile, String filename, Integer numWells,
Integer[] concentrations, Double dropOutRate){ Integer[] concentrations, Double dropOutRate){
CellFileReader cellReader = new CellFileReader(cellFile); CellFileReader cellReader = new CellFileReader(cellFile);
Double stdDev = Math.sqrt(cellReader.getCellCount()); Double stdDev = Math.sqrt(cellReader.getCellCountDEPRECATED());
Plate samplePlate = new Plate(numWells, dropOutRate, concentrations); Plate samplePlate = new Plate(numWells, dropOutRate, concentrations);
samplePlate.fillWells(cellReader.getFilename(), cellReader.getCells(), stdDev); samplePlate.fillWells(cellReader.getFilename(), cellReader.getListOfDistinctCellsDEPRECATED(), stdDev);
PlateFileWriter writer = new PlateFileWriter(filename, samplePlate); PlateFileWriter writer = new PlateFileWriter(filename, samplePlate);
writer.writePlateFile(); writer.writePlateFile();
} }
@@ -316,7 +316,7 @@ public class CommandLineInterface {
Integer numWells, Integer[] concentrations, Double dropOutRate){ Integer numWells, Integer[] concentrations, Double dropOutRate){
CellFileReader cellReader = new CellFileReader(cellFile); CellFileReader cellReader = new CellFileReader(cellFile);
Plate samplePlate = new Plate(numWells, dropOutRate, concentrations); Plate samplePlate = new Plate(numWells, dropOutRate, concentrations);
samplePlate.fillWells(cellReader.getFilename(), cellReader.getCells(), stdDev); samplePlate.fillWells(cellReader.getFilename(), cellReader.getListOfDistinctCellsDEPRECATED(), stdDev);
PlateFileWriter writer = new PlateFileWriter(filename, samplePlate); PlateFileWriter writer = new PlateFileWriter(filename, samplePlate);
writer.writePlateFile(); writer.writePlateFile();
} }

View File

@@ -4,10 +4,6 @@ import java.math.MathContext;
public abstract class Equations { public abstract class Equations {
public static int getRandomNumber(int min, int max) {
return (int) ((Math.random() * (max - min)) + min);
}
//pValue calculation as described in original pairSEQ paper. //pValue calculation as described in original pairSEQ paper.
//Included for comparison with original results. //Included for comparison with original results.
//Not used by BiGpairSEQ for matching. //Not used by BiGpairSEQ for matching.

View File

@@ -11,7 +11,7 @@ public class GraphWithMapData implements java.io.Serializable {
private String sourceFilename; private String sourceFilename;
private final SimpleWeightedGraph graph; private final SimpleWeightedGraph graph;
private Integer numWells; private Integer numWells;
private Integer[] wellConcentrations; private Integer[] wellPopulations;
private Integer alphaCount; private Integer alphaCount;
private Integer betaCount; private Integer betaCount;
private final Map<Integer, Integer> distCellsMapAlphaKey; private final Map<Integer, Integer> distCellsMapAlphaKey;
@@ -31,7 +31,7 @@ public class GraphWithMapData implements java.io.Serializable {
Map<Integer, Integer> betaWellCounts, Duration time) { Map<Integer, Integer> betaWellCounts, Duration time) {
this.graph = graph; this.graph = graph;
this.numWells = numWells; this.numWells = numWells;
this.wellConcentrations = wellConcentrations; this.wellPopulations = wellConcentrations;
this.alphaCount = alphaCount; this.alphaCount = alphaCount;
this.betaCount = betaCount; this.betaCount = betaCount;
this.distCellsMapAlphaKey = distCellsMapAlphaKey; this.distCellsMapAlphaKey = distCellsMapAlphaKey;
@@ -52,8 +52,8 @@ public class GraphWithMapData implements java.io.Serializable {
return numWells; return numWells;
} }
public Integer[] getWellConcentrations() { public Integer[] getWellPopulations() {
return wellConcentrations; return wellPopulations;
} }
public Integer getAlphaCount() { public Integer getAlphaCount() {

View File

@@ -1,14 +1,15 @@
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.*;
import java.util.Scanner; import java.util.regex.Matcher;
import java.util.InputMismatchException; import java.util.regex.Pattern;
// //
public class InteractiveInterface { public class InteractiveInterface {
final static Scanner sc = new Scanner(System.in); private static final Random rand = BiGpairSEQ.getRand();
static int input; private static final Scanner sc = new Scanner(System.in);
static boolean quit = false; private static int input;
private static boolean quit = false;
public static void startInteractive() { public static void startInteractive() {
@@ -73,9 +74,15 @@ public class InteractiveInterface {
} }
CellSample sample = Simulator.generateCellSample(numCells, cdr1Freq); CellSample sample = Simulator.generateCellSample(numCells, cdr1Freq);
assert filename != null; assert filename != null;
System.out.println("Writing cells to file");
CellFileWriter writer = new CellFileWriter(filename, sample); CellFileWriter writer = new CellFileWriter(filename, sample);
writer.writeCellsToFile(); writer.writeCellsToFile();
System.gc(); System.out.println("Cell sample written to: " + filename);
if(BiGpairSEQ.getCellSampleInMemory() != null) {
BiGpairSEQ.clearCellSampleInMemory();
}
BiGpairSEQ.setCellSampleInMemory(sample);
BiGpairSEQ.setCellFilename(filename);
} }
//Output a CSV of sample plate //Output a CSV of sample plate
@@ -85,7 +92,7 @@ public class InteractiveInterface {
Double stdDev = 0.0; Double stdDev = 0.0;
Integer numWells = 0; Integer numWells = 0;
Integer numSections; Integer numSections;
Integer[] concentrations = {1}; Integer[] populations = {1};
Double dropOutRate = 0.0; Double dropOutRate = 0.0;
boolean poisson = false; boolean poisson = false;
boolean exponential = false; boolean exponential = false;
@@ -124,10 +131,11 @@ public class InteractiveInterface {
} }
case 3 -> { case 3 -> {
exponential = true; exponential = true;
System.out.println("Please enter lambda value for exponential distribution."); System.out.print("Please enter lambda value for exponential distribution: ");
lambda = sc.nextDouble(); lambda = sc.nextDouble();
if (lambda <= 0.0) { if (lambda <= 0.0) {
throw new InputMismatchException("Value must be positive."); lambda = 0.6;
System.out.println("Value must be positive. Defaulting to 0.6.");
} }
} }
default -> { default -> {
@@ -140,22 +148,57 @@ public class InteractiveInterface {
if(numWells < 1){ if(numWells < 1){
throw new InputMismatchException("No wells on plate"); throw new InputMismatchException("No wells on plate");
} }
System.out.println("\nThe plate can be evenly sectioned to allow multiple concentrations of T-cells/well"); //choose whether to make T cell population/well random
System.out.println("How many sections would you like to make (minimum 1)?"); boolean randomWellPopulations;
numSections = sc.nextInt(); System.out.println("Randomize number of T cells in each well? (y/n)");
if(numSections < 1) { String ans = sc.next();
throw new InputMismatchException("Too few sections."); Pattern pattern = Pattern.compile("(?:yes|y)", Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(ans);
if(matcher.matches()){
randomWellPopulations = true;
} }
else if (numSections > numWells) { else{
throw new InputMismatchException("Cannot have more sections than wells."); randomWellPopulations = false;
} }
int i = 1; if(randomWellPopulations) { //if T cell population/well is random
concentrations = new Integer[numSections]; numSections = numWells;
while(numSections > 0) { Integer minPop;
System.out.print("Enter number of T-cells per well in section " + i +": "); Integer maxPop;
concentrations[i - 1] = sc.nextInt(); System.out.print("Please enter minimum number of T cells in a well: ");
i++; minPop = sc.nextInt();
numSections--; if(minPop < 1) {
throw new InputMismatchException("Minimum well population must be positive");
}
System.out.println("Please enter maximum number of T cells in a well: ");
maxPop = sc.nextInt();
if(maxPop < minPop) {
throw new InputMismatchException("Max well population must be greater than min well population");
}
//maximum should be inclusive, so need to add one to max of randomly generated values
populations = rand.ints(minPop, maxPop + 1)
.limit(numSections)
.boxed()
.toArray(Integer[]::new);
System.out.print("Populations: ");
System.out.println(Arrays.toString(populations));
}
else{ //if T cell population/well is not random
System.out.println("\nThe plate can be evenly sectioned to allow different numbers of T cells per well.");
System.out.println("How many sections would you like to make (minimum 1)?");
numSections = sc.nextInt();
if (numSections < 1) {
throw new InputMismatchException("Too few sections.");
} else if (numSections > numWells) {
throw new InputMismatchException("Cannot have more sections than wells.");
}
int i = 1;
populations = new Integer[numSections];
while (numSections > 0) {
System.out.print("Enter number of T cells per well in section " + i + ": ");
populations[i - 1] = sc.nextInt();
i++;
numSections--;
}
} }
System.out.println("\nErrors in amplification can induce a well dropout rate for sequences"); System.out.println("\nErrors in amplification can induce a well dropout rate for sequences");
System.out.print("Enter well dropout rate (0.0 to 1.0): "); System.out.print("Enter well dropout rate (0.0 to 1.0): ");
@@ -167,28 +210,40 @@ public class InteractiveInterface {
System.out.println(ex); System.out.println(ex);
sc.next(); sc.next();
} }
System.out.println("Reading Cell Sample file: " + cellFile);
assert cellFile != null; assert cellFile != null;
CellFileReader cellReader = new CellFileReader(cellFile); CellSample cells;
if (cellFile.equals(BiGpairSEQ.getCellFilename())){
cells = BiGpairSEQ.getCellSampleInMemory();
}
else {
System.out.println("Reading Cell Sample file: " + cellFile);
CellFileReader cellReader = new CellFileReader(cellFile);
cells = cellReader.getCellSample();
BiGpairSEQ.clearCellSampleInMemory();
BiGpairSEQ.setCellSampleInMemory(cells);
BiGpairSEQ.setCellFilename(cellFile);
}
assert filename != null;
Plate samplePlate;
PlateFileWriter writer;
if(exponential){ if(exponential){
Plate samplePlate = new Plate(numWells, dropOutRate, concentrations); samplePlate = new Plate(numWells, dropOutRate, populations);
samplePlate.fillWellsExponential(cellReader.getFilename(), cellReader.getCells(), lambda); samplePlate.fillWellsExponential(cellFile, cells.getCells(), lambda);
PlateFileWriter writer = new PlateFileWriter(filename, samplePlate); writer = new PlateFileWriter(filename, samplePlate);
writer.writePlateFile();
} }
else { else {
if (poisson) { if (poisson) {
stdDev = Math.sqrt(cellReader.getCellCount()); //gaussian with square root of elements approximates poisson stdDev = Math.sqrt(cells.getCellCount()); //gaussian with square root of elements approximates poisson
} }
Plate samplePlate = new Plate(numWells, dropOutRate, concentrations); samplePlate = new Plate(numWells, dropOutRate, populations);
samplePlate.fillWells(cellReader.getFilename(), cellReader.getCells(), stdDev); samplePlate.fillWells(cellFile, cells.getCells(), stdDev);
assert filename != null; writer = new PlateFileWriter(filename, samplePlate);
PlateFileWriter writer = new PlateFileWriter(filename, samplePlate);
System.out.println("Writing Sample Plate to file");
writer.writePlateFile();
System.out.println("Sample Plate written to file: " + filename);
System.gc();
} }
System.out.println("Writing Sample Plate to file");
writer.writePlateFile();
System.out.println("Sample Plate written to file: " + filename);
BiGpairSEQ.setPlateInMemory(samplePlate);
BiGpairSEQ.setPlateFilename(filename);
} }
//Output serialized binary of GraphAndMapData object //Output serialized binary of GraphAndMapData object
@@ -212,14 +267,37 @@ public class InteractiveInterface {
System.out.println(ex); System.out.println(ex);
sc.next(); sc.next();
} }
System.out.println("Reading Cell Sample file: " + cellFile);
assert cellFile != null; assert cellFile != null;
CellFileReader cellReader = new CellFileReader(cellFile); CellSample cellSample;
System.out.println("Reading Sample Plate file: " + plateFile); //check if cells are already in memory
if(cellFile.equals(BiGpairSEQ.getCellFilename())) {
cellSample = BiGpairSEQ.getCellSampleInMemory();
}
else {
BiGpairSEQ.clearCellSampleInMemory();
System.out.println("Reading Cell Sample file: " + cellFile);
CellFileReader cellReader = new CellFileReader(cellFile);
cellSample = cellReader.getCellSample();
BiGpairSEQ.setCellSampleInMemory(cellSample);
BiGpairSEQ.setCellFilename(cellFile);
}
assert plateFile != null; assert plateFile != null;
PlateFileReader plateReader = new PlateFileReader(plateFile); Plate plate;
Plate plate = new Plate(plateReader.getFilename(), plateReader.getWells()); //check if plate is already in memory
if (cellReader.getCells().size() == 0){ if(plateFile.equals(BiGpairSEQ.getPlateFilename())){
plate = BiGpairSEQ.getPlateInMemory();
}
else {
BiGpairSEQ.clearPlateInMemory();
System.out.println("Reading Sample Plate file: " + plateFile);
PlateFileReader plateReader = new PlateFileReader(plateFile);
plate = new Plate(plateReader.getFilename(), plateReader.getWells());
BiGpairSEQ.setPlateInMemory(plate);
BiGpairSEQ.setPlateFilename(plateFile);
}
if (cellSample.getCells().size() == 0){
System.out.println("No cell sample found."); System.out.println("No cell sample found.");
System.out.println("Returning to main menu."); System.out.println("Returning to main menu.");
} }
@@ -228,13 +306,15 @@ public class InteractiveInterface {
System.out.println("Returning to main menu."); System.out.println("Returning to main menu.");
} }
else{ else{
List<Integer[]> cells = cellReader.getCells(); List<Integer[]> cells = cellSample.getCells();
GraphWithMapData data = Simulator.makeGraph(cells, plate, true); GraphWithMapData data = Simulator.makeGraph(cells, plate, true);
assert filename != null; assert filename != null;
GraphDataObjectWriter dataWriter = new GraphDataObjectWriter(filename, data); GraphDataObjectWriter dataWriter = new GraphDataObjectWriter(filename, data);
dataWriter.writeDataToFile(); dataWriter.writeDataToFile();
System.out.println("Graph and Data file written to: " + filename); System.out.println("Graph and Data file written to: " + filename);
System.gc(); BiGpairSEQ.setGraphInMemory(data);
BiGpairSEQ.setGraphFilename(filename);
System.out.println("Graph and Data file " + filename + " cached.");
} }
} }
@@ -256,17 +336,28 @@ public class InteractiveInterface {
System.out.println("\nWhat is the minimum number of CDR3 alpha/beta overlap wells to attempt matching?"); System.out.println("\nWhat is the minimum number of CDR3 alpha/beta overlap wells to attempt matching?");
lowThreshold = sc.nextInt(); lowThreshold = sc.nextInt();
if(lowThreshold < 1){ if(lowThreshold < 1){
throw new InputMismatchException("Minimum value for low threshold set to 1"); lowThreshold = 1;
System.out.println("Value for low occupancy overlap threshold must be positive");
System.out.println("Value for low occupancy overlap threshold set to 1");
} }
System.out.println("\nWhat is the maximum number of CDR3 alpha/beta overlap wells to attempt matching?"); System.out.println("\nWhat is the maximum number of CDR3 alpha/beta overlap wells to attempt matching?");
highThreshold = sc.nextInt(); highThreshold = sc.nextInt();
System.out.println("\nWhat is the maximum difference in alpha/beta occupancy to attempt matching?"); if(highThreshold < lowThreshold) {
maxOccupancyDiff = sc.nextInt(); highThreshold = lowThreshold;
System.out.println("\nWell overlap percentage = pair overlap / sequence occupancy"); System.out.println("Value for high occupancy overlap threshold must be >= low overlap threshold");
System.out.println("What is the minimum well overlap percentage to attempt matching? (0 to 100)"); System.out.println("Value for high occupancy overlap threshold set to " + lowThreshold);
}
System.out.println("What is the minimum percentage of a sequence's wells in alpha/beta overlap to attempt matching? (0 - 100)");
minOverlapPercent = sc.nextInt(); minOverlapPercent = sc.nextInt();
if (minOverlapPercent < 0 || minOverlapPercent > 100) { if (minOverlapPercent < 0 || minOverlapPercent > 100) {
throw new InputMismatchException("Value outside range. Minimum percent set to 0"); System.out.println("Value outside range. Minimum occupancy overlap percentage set to 0");
}
System.out.println("\nWhat is the maximum difference in alpha/beta occupancy to attempt matching?");
maxOccupancyDiff = sc.nextInt();
if (maxOccupancyDiff < 0) {
maxOccupancyDiff = 0;
System.out.println("Maximum allowable difference in alpha/beta occupancy must be nonnegative");
System.out.println("Maximum allowable difference in alpha/beta occupancy set to 0");
} }
} catch (InputMismatchException ex) { } catch (InputMismatchException ex) {
System.out.println(ex); System.out.println(ex);
@@ -275,17 +366,17 @@ public class InteractiveInterface {
assert graphFilename != null; assert graphFilename != null;
//check if this is the same graph we already have in memory. //check if this is the same graph we already have in memory.
GraphWithMapData data; GraphWithMapData data;
if(!(graphFilename.equals(BiGpairSEQ.getGraphFilename())) || BiGpairSEQ.getGraph() == null) { if(!(graphFilename.equals(BiGpairSEQ.getGraphFilename())) || BiGpairSEQ.getGraphInMemory() == null) {
BiGpairSEQ.clearGraph(); BiGpairSEQ.clearGraphInMemory();
//read object data from file //read object data from file
GraphDataObjectReader dataReader = new GraphDataObjectReader(graphFilename); GraphDataObjectReader dataReader = new GraphDataObjectReader(graphFilename);
data = dataReader.getData(); data = dataReader.getData();
//set new graph in memory and new filename //set new graph in memory and new filename
BiGpairSEQ.setGraph(data); BiGpairSEQ.setGraphInMemory(data);
BiGpairSEQ.setGraphFilename(graphFilename); BiGpairSEQ.setGraphFilename(graphFilename);
} }
else { else {
data = BiGpairSEQ.getGraph(); data = BiGpairSEQ.getGraphInMemory();
} }
//simulate matching //simulate matching
MatchingResult results = Simulator.matchCDR3s(data, graphFilename, lowThreshold, highThreshold, maxOccupancyDiff, MatchingResult results = Simulator.matchCDR3s(data, graphFilename, lowThreshold, highThreshold, maxOccupancyDiff,
@@ -296,7 +387,6 @@ public class InteractiveInterface {
System.out.println("Writing results to file"); System.out.println("Writing results to file");
writer.writeResultsToFile(); writer.writeResultsToFile();
System.out.println("Results written to file: " + filename); System.out.println("Results written to file: " + filename);
System.gc();
} }
/////// ///////

View File

@@ -10,7 +10,7 @@ import java.util.*;
public class Plate { public class Plate {
private String sourceFile; private String sourceFile;
private List<List<Integer[]>> wells; private List<List<Integer[]>> wells;
private Random rand = new Random(); private final Random rand = BiGpairSEQ.getRand();
private int size; private int size;
private double error; private double error;
private Integer[] populations; private Integer[] populations;
@@ -51,7 +51,6 @@ public class Plate {
int section = 0; int section = 0;
double m; double m;
int n; int n;
int test=0;
while (section < numSections){ while (section < numSections){
for (int i = 0; i < (size / numSections); i++) { for (int i = 0; i < (size / numSections); i++) {
List<Integer[]> well = new ArrayList<>(); List<Integer[]> well = new ArrayList<>();
@@ -61,13 +60,6 @@ public class Plate {
m = (Math.log10((1 - rand.nextDouble()))/(-lambda)) * Math.sqrt(cells.size()); m = (Math.log10((1 - rand.nextDouble()))/(-lambda)) * Math.sqrt(cells.size());
} while (m >= cells.size() || m < 0); } while (m >= cells.size() || m < 0);
n = (int) Math.floor(m); n = (int) Math.floor(m);
//n = Equations.getRandomNumber(0, cells.size());
// was testing generating the cell sample file with exponential dist, then sampling flat here
//that would be more realistic
//But would mess up other things in the simulation with how I've coded it.
if(n > test){
test = n;
}
Integer[] cellToAdd = cells.get(n).clone(); Integer[] cellToAdd = cells.get(n).clone();
for(int k = 0; k < cellToAdd.length; k++){ for(int k = 0; k < cellToAdd.length; k++){
if(Math.abs(rand.nextDouble()) < error){//error applied to each seqeunce if(Math.abs(rand.nextDouble()) < error){//error applied to each seqeunce
@@ -80,7 +72,6 @@ public class Plate {
} }
section++; section++;
} }
System.out.println("Highest index: " +test);
} }
public void fillWells(String sourceFileName, List<Integer[]> cells, double stdDev) { public void fillWells(String sourceFileName, List<Integer[]> cells, double stdDev) {

View File

@@ -16,7 +16,7 @@ public class PlateFileWriter {
private Double error; private Double error;
private String filename; private String filename;
private String sourceFileName; private String sourceFileName;
private Integer[] concentrations; private Integer[] populations;
private boolean isExponential = false; private boolean isExponential = false;
public PlateFileWriter(String filename, Plate plate) { public PlateFileWriter(String filename, Plate plate) {
@@ -35,8 +35,8 @@ public class PlateFileWriter {
} }
this.error = plate.getError(); this.error = plate.getError();
this.wells = plate.getWells(); this.wells = plate.getWells();
this.concentrations = plate.getPopulations(); this.populations = plate.getPopulations();
Arrays.sort(concentrations); Arrays.sort(populations);
} }
public void writePlateFile(){ public void writePlateFile(){
@@ -73,14 +73,12 @@ public class PlateFileWriter {
// rows.add(tmp); // rows.add(tmp);
// } // }
//get list of well populations //make string out of populations array
List<Integer> wellPopulations = Arrays.asList(concentrations);
//make string out of populations list
StringBuilder populationsStringBuilder = new StringBuilder(); StringBuilder populationsStringBuilder = new StringBuilder();
populationsStringBuilder.append(wellPopulations.remove(0).toString()); populationsStringBuilder.append(populations[0].toString());
for(Integer i: wellPopulations){ for(int i = 1; i < populations.length; i++){
populationsStringBuilder.append(", "); populationsStringBuilder.append(", ");
populationsStringBuilder.append(i.toString()); populationsStringBuilder.append(populations[i].toString());
} }
String wellPopulationsString = populationsStringBuilder.toString(); String wellPopulationsString = populationsStringBuilder.toString();

View File

@@ -1,4 +1,3 @@
import org.jgrapht.Graph;
import org.jgrapht.alg.interfaces.MatchingAlgorithm; import org.jgrapht.alg.interfaces.MatchingAlgorithm;
import org.jgrapht.alg.matching.MaximumWeightBipartiteMatching; import org.jgrapht.alg.matching.MaximumWeightBipartiteMatching;
import org.jgrapht.generate.SimpleWeightedBipartiteGraphMatrixGenerator; import org.jgrapht.generate.SimpleWeightedBipartiteGraphMatrixGenerator;
@@ -14,6 +13,8 @@ import java.time.Duration;
import java.util.*; import java.util.*;
import java.util.stream.IntStream; import java.util.stream.IntStream;
import static java.lang.Float.*;
//NOTE: "sequence" in method and variable names refers to a peptide sequence from a simulated T cell //NOTE: "sequence" in method and variable names refers to a peptide sequence from a simulated T cell
public class Simulator { public class Simulator {
private static final int cdr3AlphaIndex = 0; private static final int cdr3AlphaIndex = 0;
@@ -247,10 +248,16 @@ public class Simulator {
BigDecimal attemptRateTrunc = new BigDecimal(attemptRate, mc); BigDecimal attemptRateTrunc = new BigDecimal(attemptRate, mc);
//rate of pairing error //rate of pairing error
double pairingErrorRate = (double) falseCount / (trueCount + falseCount); double pairingErrorRate = (double) falseCount / (trueCount + falseCount);
BigDecimal pairingErrorRateTrunc = new BigDecimal(pairingErrorRate, mc); BigDecimal pairingErrorRateTrunc;
//get list of well concentrations if(pairingErrorRate == NaN || pairingErrorRate == POSITIVE_INFINITY || pairingErrorRate == NEGATIVE_INFINITY) {
Integer[] wellPopulations = data.getWellConcentrations(); pairingErrorRateTrunc = new BigDecimal(-1, mc);
//make string out of concentrations list }
else{
pairingErrorRateTrunc = new BigDecimal(pairingErrorRate, mc);
}
//get list of well populations
Integer[] wellPopulations = data.getWellPopulations();
//make string out of populations list
StringBuilder populationsStringBuilder = new StringBuilder(); StringBuilder populationsStringBuilder = new StringBuilder();
populationsStringBuilder.append(wellPopulations[0].toString()); populationsStringBuilder.append(wellPopulations[0].toString());
for(int i = 1; i < wellPopulations.length; i++){ for(int i = 1; i < wellPopulations.length; i++){
@@ -270,8 +277,8 @@ public class Simulator {
metadata.put("total betas found", betaCount.toString()); metadata.put("total betas found", betaCount.toString());
metadata.put("high overlap threshold", highThreshold.toString()); metadata.put("high overlap threshold", highThreshold.toString());
metadata.put("low overlap threshold", lowThreshold.toString()); metadata.put("low overlap threshold", lowThreshold.toString());
metadata.put("maximum occupancy difference", maxOccupancyDifference.toString());
metadata.put("minimum overlap percent", minOverlapPercent.toString()); metadata.put("minimum overlap percent", minOverlapPercent.toString());
metadata.put("maximum occupancy difference", maxOccupancyDifference.toString());
metadata.put("pairing attempt rate", attemptRateTrunc.toString()); metadata.put("pairing attempt rate", attemptRateTrunc.toString());
metadata.put("correct pairing count", Integer.toString(trueCount)); metadata.put("correct pairing count", Integer.toString(trueCount));
metadata.put("incorrect pairing count", Integer.toString(falseCount)); metadata.put("incorrect pairing count", Integer.toString(falseCount));