Compare commits
27 Commits
a5db89cb0b
...
v1.4
| Author | SHA1 | Date | |
|---|---|---|---|
| ab8d98ed81 | |||
| 3d9890e16a | |||
| dd64ac2731 | |||
| a5238624f1 | |||
| d8ba42b801 | |||
| 8edd89d784 | |||
| 2829b88689 | |||
| 108b0ec13f | |||
| a8b58d3f79 | |||
| bf64d57731 | |||
| c068c3db3c | |||
| 4bcda9b66c | |||
| 17ae763c6c | |||
| decdb147a9 | |||
| 74ffbfd8ac | |||
| 08699ce8ce | |||
| 69b0cc535c | |||
| e58f7b0a55 | |||
| dd2164c250 | |||
| 7323093bdc | |||
| f904cf6672 | |||
| 3ccee9891b | |||
| 40c2be1cfb | |||
| 4b597c4e5e | |||
| b2398531a3 | |||
| 8e9a250890 | |||
| e2a996c997 |
62
readme.md
62
readme.md
@@ -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.)
|
||||||
@@ -29,17 +29,13 @@ Unfortunately, it's a fairly new algorithm, and not yet implemented by the graph
|
|||||||
So this program instead uses the Fibonacci heap-based algorithm of Fredman and Tarjan (1987), which has a worst-case
|
So this program instead uses the Fibonacci heap-based algorithm of Fredman and Tarjan (1987), which has a worst-case
|
||||||
runtime of **O(n (n log(n) + m))**. The algorithm is implemented as described in Melhorn and Näher (1999).
|
runtime of **O(n (n log(n) + m))**. The algorithm is implemented as described in Melhorn and Näher (1999).
|
||||||
|
|
||||||
The current version of the program uses a pairing heap instead of a Fibonacci heap for its priority queue,
|
|
||||||
which has lower theoretical efficiency but also lower complexity overhead, and is often equivalently performant
|
|
||||||
in practice.
|
|
||||||
|
|
||||||
## USAGE
|
## USAGE
|
||||||
|
|
||||||
### RUNNING THE PROGRAM
|
### RUNNING THE PROGRAM
|
||||||
|
|
||||||
[Download the current version of BiGpairSEQ_Sim.](https://gitea.ejsf.synology.me/efischer/BiGpairSEQ/releases)
|
[Download the current version of BiGpairSEQ_Sim.](https://gitea.ejsf.synology.me/efischer/BiGpairSEQ/releases)
|
||||||
|
|
||||||
BiGpairSEQ_Sim is an executable .jar file. Requires Java 11 or higher. [OpenJDK 17](https://jdk.java.net/17/)
|
BiGpairSEQ_Sim is an executable .jar file. Requires Java 14 or higher. [OpenJDK 17](https://jdk.java.net/17/)
|
||||||
recommended.
|
recommended.
|
||||||
|
|
||||||
Run with the command:
|
Run with the command:
|
||||||
@@ -58,27 +54,41 @@ main menu looks like this:
|
|||||||
```
|
```
|
||||||
--------BiGPairSEQ SIMULATOR--------
|
--------BiGPairSEQ SIMULATOR--------
|
||||||
ALPHA/BETA T CELL RECEPTOR MATCHING
|
ALPHA/BETA T CELL RECEPTOR MATCHING
|
||||||
USING WEIGHTED BIPARTITE GRAPHS
|
USING WEIGHTED BIPARTITE GRAPHS
|
||||||
------------------------------------
|
------------------------------------
|
||||||
Please select an option:
|
Please select an option:
|
||||||
1) Generate a population of distinct cells
|
1) Generate a population of distinct cells
|
||||||
2) Generate a sample plate of T cells
|
2) Generate a sample plate of T cells
|
||||||
3) Generate CDR3 alpha/beta occupancy data and overlap graph
|
3) Generate CDR3 alpha/beta occupancy data and overlap graph
|
||||||
4) Simulate bipartite graph CDR3 alpha/beta matching (BiGpairSEQ)
|
4) Simulate bipartite graph CDR3 alpha/beta matching (BiGpairSEQ)
|
||||||
|
8) Options
|
||||||
9) About/Acknowledgments
|
9) About/Acknowledgments
|
||||||
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
|
||||||
|
|
||||||
When entering filenames, it is not necessary to include the file extension (.csv or .ser). When reading or
|
These files are often generated in sequence. When entering filenames, it is not necessary to include the file extension
|
||||||
writing files, the program will automatically add the correct extension to any filename without one.
|
(.csv or .ser). When reading or writing files, the program will automatically add the correct extension to any filename without one.
|
||||||
|
|
||||||
|
To save file I/O time, the most recent instance of each of these four
|
||||||
|
files either generated or read from disk can be cached in program memory. This is could be important for Graph/Data files,
|
||||||
|
which can be several gigabytes in size. Since some simulations may require running multiple,
|
||||||
|
differently-configured BiGpairSEQ matchings on the same graph, keeping the most recent graph cached may reduce execution time.
|
||||||
|
(The manipulation necessary to re-use a graph incurs its own performance overhead, though, which may scale with graph
|
||||||
|
size faster than file I/O does. If so, caching is best for smaller graphs.)
|
||||||
|
|
||||||
|
When caching is active, 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,
|
||||||
|
or caching is turned off for that file type. 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.
|
||||||
|
|
||||||
|
The program's caching behavior can be controlled in the Options menu. By default, all caching is OFF.
|
||||||
|
|
||||||
#### 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:
|
||||||
@@ -241,7 +253,8 @@ slightly less time than the simulation itself. Real elapsed time from start to f
|
|||||||
* ~~Try invoking GC at end of workloads to reduce paging to disk~~ DONE
|
* ~~Try invoking GC at end of workloads to reduce paging to disk~~ DONE
|
||||||
* Hold graph data in memory until another graph is read-in? ~~ABANDONED~~ ~~UNABANDONED~~ DONE
|
* Hold graph data in memory until another graph is read-in? ~~ABANDONED~~ ~~UNABANDONED~~ DONE
|
||||||
* ~~*No, this won't work, because BiGpairSEQ simulations alter the underlying graph based on filtering constraints. Changes would cascade with multiple experiments.*~~
|
* ~~*No, this won't work, because BiGpairSEQ simulations alter the underlying graph based on filtering constraints. Changes would cascade with multiple experiments.*~~
|
||||||
* Might have figured out a way to do it, by taking edges out and then putting them back into the graph. This may actually be possible. If so, awesome.
|
* Might have figured out a way to do it, by taking edges out and then putting them back into the graph. This may actually be possible.
|
||||||
|
* It is possible, though the modifications to the graph incur their own performance penalties. Need testing to see which option is best.
|
||||||
* See if there's a reasonable way to reformat Sample Plate files so that wells are columns instead of rows.
|
* See if there's a reasonable way to reformat Sample Plate files so that wells are columns instead of rows.
|
||||||
* ~~Problem is variable number of cells in a well~~
|
* ~~Problem is variable number of cells in a well~~
|
||||||
* ~~Apache Commons CSV library writes entries a row at a time~~
|
* ~~Apache Commons CSV library writes entries a row at a time~~
|
||||||
@@ -255,9 +268,10 @@ slightly less time than the simulation itself. Real elapsed time from start to f
|
|||||||
* Re-implement CDR1 matching method
|
* Re-implement CDR1 matching method
|
||||||
* Implement Duan and Su's maximum weight matching algorithm
|
* Implement Duan and Su's maximum weight matching algorithm
|
||||||
* Add controllable algorithm-type parameter?
|
* Add controllable algorithm-type parameter?
|
||||||
* Test whether pairing heap (currently used) or Fibonacci heap is more efficient for priority queue in current matching algorithm
|
* ~~Test whether pairing heap (currently used) or Fibonacci heap is more efficient for priority queue in current matching algorithm~~ DONE
|
||||||
* in theory Fibonacci heap should be more efficient, but complexity overhead may eliminate theoretical advantage
|
* ~~in theory Fibonacci heap should be more efficient, but complexity overhead may eliminate theoretical advantage~~
|
||||||
* Add controllable heap-type parameter?
|
* ~~Add controllable heap-type parameter?~~
|
||||||
|
* Parameter implemented. For large graphs, Fibonacci heap wins. Now the new default.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,19 @@
|
|||||||
//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;
|
||||||
|
private static boolean cacheCells = false;
|
||||||
|
private static boolean cachePlate = false;
|
||||||
|
private static boolean cacheGraph = false;
|
||||||
|
private static String priorityQueueHeapType = "FIBONACCI";
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
if (args.length == 0) {
|
if (args.length == 0) {
|
||||||
@@ -15,28 +26,142 @@ public class BiGpairSEQ {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static GraphWithMapData getGraph() {
|
public static Random getRand() {
|
||||||
return graphInMemory;
|
return rand;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setGraph(GraphWithMapData g) {
|
public static CellSample getCellSampleInMemory() {
|
||||||
|
return cellSampleInMemory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setCellSampleInMemory(CellSample cellSample, String filename) {
|
||||||
|
if(cellSampleInMemory != null) {
|
||||||
|
clearCellSampleInMemory();
|
||||||
|
}
|
||||||
|
cellSampleInMemory = cellSample;
|
||||||
|
cellFilename = filename;
|
||||||
|
System.out.println("Cell sample file " + filename + " cached.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void clearCellSampleInMemory() {
|
||||||
|
cellSampleInMemory = null;
|
||||||
|
cellFilename = null;
|
||||||
|
System.gc();
|
||||||
|
System.out.println("Cell sample file cache cleared.");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getCellFilename() {
|
||||||
|
return cellFilename;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Plate getPlateInMemory() {
|
||||||
|
return plateInMemory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setPlateInMemory(Plate plate, String filename) {
|
||||||
|
if(plateInMemory != null) {
|
||||||
|
clearPlateInMemory();
|
||||||
|
}
|
||||||
|
plateInMemory = plate;
|
||||||
|
plateFilename = filename;
|
||||||
|
System.out.println("Sample plate file " + filename + " cached.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void clearPlateInMemory() {
|
||||||
|
plateInMemory = null;
|
||||||
|
plateFilename = null;
|
||||||
|
System.gc();
|
||||||
|
System.out.println("Sample plate file cache cleared.");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getPlateFilename() {
|
||||||
|
return plateFilename;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static GraphWithMapData getGraphInMemory() {return graphInMemory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setGraphInMemory(GraphWithMapData g, String filename) {
|
||||||
if (graphInMemory != null) {
|
if (graphInMemory != null) {
|
||||||
clearGraph();
|
clearGraphInMemory();
|
||||||
}
|
}
|
||||||
graphInMemory = g;
|
graphInMemory = g;
|
||||||
|
graphFilename = filename;
|
||||||
|
System.out.println("Graph and data file " + filename + " cached.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void clearGraph() {
|
public static void clearGraphInMemory() {
|
||||||
graphInMemory = null;
|
graphInMemory = null;
|
||||||
|
graphFilename = null;
|
||||||
System.gc();
|
System.gc();
|
||||||
|
System.out.println("Graph and data file cache cleared.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getGraphFilename() {
|
public static String getGraphFilename() {
|
||||||
return graphFilename;
|
return graphFilename;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setGraphFilename(String filename) {
|
|
||||||
graphFilename = filename;
|
public static boolean cacheCells() {
|
||||||
|
return cacheCells;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void setCacheCells(boolean cacheCells) {
|
||||||
|
//if not caching, clear the memory
|
||||||
|
if(!cacheCells){
|
||||||
|
BiGpairSEQ.clearCellSampleInMemory();
|
||||||
|
System.out.println("Cell sample file caching: OFF.");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
System.out.println("Cell sample file caching: ON.");
|
||||||
|
}
|
||||||
|
BiGpairSEQ.cacheCells = cacheCells;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean cachePlate() {
|
||||||
|
return cachePlate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setCachePlate(boolean cachePlate) {
|
||||||
|
//if not caching, clear the memory
|
||||||
|
if(!cachePlate) {
|
||||||
|
BiGpairSEQ.clearPlateInMemory();
|
||||||
|
System.out.println("Sample plate file caching: OFF.");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
System.out.println("Sample plate file caching: ON.");
|
||||||
|
}
|
||||||
|
BiGpairSEQ.cachePlate = cachePlate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean cacheGraph() {
|
||||||
|
return cacheGraph;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setCacheGraph(boolean cacheGraph) {
|
||||||
|
//if not caching, clear the memory
|
||||||
|
if(!cacheGraph) {
|
||||||
|
BiGpairSEQ.clearGraphInMemory();
|
||||||
|
System.out.println("Graph/data file caching: OFF.");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
System.out.println("Graph/data file caching: ON.");
|
||||||
|
}
|
||||||
|
BiGpairSEQ.cacheGraph = cacheGraph;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getPriorityQueueHeapType() {
|
||||||
|
return priorityQueueHeapType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setPairingHeap() {
|
||||||
|
priorityQueueHeapType = "PAIRING";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setFibonacciHeap() {
|
||||||
|
priorityQueueHeapType = "FIBONACCI";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ public class CellSample {
|
|||||||
return cdr1Freq;
|
return cdr1Freq;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Integer population(){
|
public Integer getCellCount(){
|
||||||
return cells.size();
|
return cells.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -6,59 +6,74 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public abstract class GraphModificationFunctions {
|
public interface GraphModificationFunctions {
|
||||||
|
|
||||||
//remove over- and under-weight edges
|
//remove over- and under-weight edges
|
||||||
public static List<Integer[]> filterByOverlapThresholds(SimpleWeightedGraph<Integer, DefaultWeightedEdge> graph,
|
static List<Integer[]> filterByOverlapThresholds(SimpleWeightedGraph<Integer, DefaultWeightedEdge> graph,
|
||||||
int low, int high) {
|
int low, int high, boolean saveEdges) {
|
||||||
List<Integer[]> removedEdges = new ArrayList<>();
|
List<Integer[]> removedEdges = new ArrayList<>();
|
||||||
for(DefaultWeightedEdge e: graph.edgeSet()){
|
for (DefaultWeightedEdge e : graph.edgeSet()) {
|
||||||
if ((graph.getEdgeWeight(e) > high) || (graph.getEdgeWeight(e) < low)){
|
if ((graph.getEdgeWeight(e) > high) || (graph.getEdgeWeight(e) < low)) {
|
||||||
Integer source = graph.getEdgeSource(e);
|
if(saveEdges) {
|
||||||
Integer target = graph.getEdgeTarget(e);
|
Integer source = graph.getEdgeSource(e);
|
||||||
Integer weight = (int) graph.getEdgeWeight(e);
|
Integer target = graph.getEdgeTarget(e);
|
||||||
Integer[] edge = {source, target, weight};
|
Integer weight = (int) graph.getEdgeWeight(e);
|
||||||
removedEdges.add(edge);
|
Integer[] edge = {source, target, weight};
|
||||||
|
removedEdges.add(edge);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
graph.setEdgeWeight(e, 0.0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (Integer[] edge : removedEdges) {
|
if(saveEdges) {
|
||||||
graph.removeEdge(edge[0], edge[1]);
|
for (Integer[] edge : removedEdges) {
|
||||||
|
graph.removeEdge(edge[0], edge[1]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return removedEdges;
|
return removedEdges;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Remove edges for pairs with large occupancy discrepancy
|
//Remove edges for pairs with large occupancy discrepancy
|
||||||
public static List<Integer[]> filterByRelativeOccupancy(SimpleWeightedGraph<Integer, DefaultWeightedEdge> graph,
|
static List<Integer[]> filterByRelativeOccupancy(SimpleWeightedGraph<Integer, DefaultWeightedEdge> graph,
|
||||||
Map<Integer, Integer> alphaWellCounts,
|
Map<Integer, Integer> alphaWellCounts,
|
||||||
Map<Integer, Integer> betaWellCounts,
|
Map<Integer, Integer> betaWellCounts,
|
||||||
Map<Integer, Integer> plateVtoAMap,
|
Map<Integer, Integer> plateVtoAMap,
|
||||||
Map<Integer, Integer> plateVtoBMap,
|
Map<Integer, Integer> plateVtoBMap,
|
||||||
Integer maxOccupancyDifference) {
|
Integer maxOccupancyDifference, boolean saveEdges) {
|
||||||
List<Integer[]> removedEdges = new ArrayList<>();
|
List<Integer[]> removedEdges = new ArrayList<>();
|
||||||
for (DefaultWeightedEdge e : graph.edgeSet()) {
|
for (DefaultWeightedEdge e : graph.edgeSet()) {
|
||||||
Integer alphaOcc = alphaWellCounts.get(plateVtoAMap.get(graph.getEdgeSource(e)));
|
Integer alphaOcc = alphaWellCounts.get(plateVtoAMap.get(graph.getEdgeSource(e)));
|
||||||
Integer betaOcc = betaWellCounts.get(plateVtoBMap.get(graph.getEdgeTarget(e)));
|
Integer betaOcc = betaWellCounts.get(plateVtoBMap.get(graph.getEdgeTarget(e)));
|
||||||
if (Math.abs(alphaOcc - betaOcc) >= maxOccupancyDifference) {
|
if (Math.abs(alphaOcc - betaOcc) >= maxOccupancyDifference) {
|
||||||
Integer source = graph.getEdgeSource(e);
|
if (saveEdges) {
|
||||||
Integer target = graph.getEdgeTarget(e);
|
Integer source = graph.getEdgeSource(e);
|
||||||
Integer weight = (int) graph.getEdgeWeight(e);
|
Integer target = graph.getEdgeTarget(e);
|
||||||
Integer[] edge = {source, target, weight};
|
Integer weight = (int) graph.getEdgeWeight(e);
|
||||||
removedEdges.add(edge);
|
Integer[] edge = {source, target, weight};
|
||||||
|
removedEdges.add(edge);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
graph.setEdgeWeight(e, 0.0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (Integer[] edge : removedEdges) {
|
if(saveEdges) {
|
||||||
graph.removeEdge(edge[0], edge[1]);
|
for (Integer[] edge : removedEdges) {
|
||||||
|
graph.removeEdge(edge[0], edge[1]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return removedEdges;
|
return removedEdges;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Remove edges for pairs where overlap size is significantly lower than the well occupancy
|
//Remove edges for pairs where overlap size is significantly lower than the well occupancy
|
||||||
public static List<Integer[]> filterByOverlapPercent(SimpleWeightedGraph<Integer, DefaultWeightedEdge> graph,
|
static List<Integer[]> filterByOverlapPercent(SimpleWeightedGraph<Integer, DefaultWeightedEdge> graph,
|
||||||
Map<Integer, Integer> alphaWellCounts,
|
Map<Integer, Integer> alphaWellCounts,
|
||||||
Map<Integer, Integer> betaWellCounts,
|
Map<Integer, Integer> betaWellCounts,
|
||||||
Map<Integer, Integer> plateVtoAMap,
|
Map<Integer, Integer> plateVtoAMap,
|
||||||
Map<Integer, Integer> plateVtoBMap,
|
Map<Integer, Integer> plateVtoBMap,
|
||||||
Integer minOverlapPercent) {
|
Integer minOverlapPercent,
|
||||||
|
boolean saveEdges) {
|
||||||
List<Integer[]> removedEdges = new ArrayList<>();
|
List<Integer[]> removedEdges = new ArrayList<>();
|
||||||
for (DefaultWeightedEdge e : graph.edgeSet()) {
|
for (DefaultWeightedEdge e : graph.edgeSet()) {
|
||||||
Integer alphaOcc = alphaWellCounts.get(plateVtoAMap.get(graph.getEdgeSource(e)));
|
Integer alphaOcc = alphaWellCounts.get(plateVtoAMap.get(graph.getEdgeSource(e)));
|
||||||
@@ -66,20 +81,27 @@ public abstract class GraphModificationFunctions {
|
|||||||
double weight = graph.getEdgeWeight(e);
|
double weight = graph.getEdgeWeight(e);
|
||||||
double min = minOverlapPercent / 100.0;
|
double min = minOverlapPercent / 100.0;
|
||||||
if ((weight / alphaOcc < min) || (weight / betaOcc < min)) {
|
if ((weight / alphaOcc < min) || (weight / betaOcc < min)) {
|
||||||
Integer source = graph.getEdgeSource(e);
|
if(saveEdges) {
|
||||||
Integer target = graph.getEdgeTarget(e);
|
Integer source = graph.getEdgeSource(e);
|
||||||
Integer intWeight = (int) graph.getEdgeWeight(e);
|
Integer target = graph.getEdgeTarget(e);
|
||||||
Integer[] edge = {source, target, intWeight};
|
Integer intWeight = (int) graph.getEdgeWeight(e);
|
||||||
removedEdges.add(edge);
|
Integer[] edge = {source, target, intWeight};
|
||||||
|
removedEdges.add(edge);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
graph.setEdgeWeight(e, 0.0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (Integer[] edge : removedEdges) {
|
if(saveEdges) {
|
||||||
graph.removeEdge(edge[0], edge[1]);
|
for (Integer[] edge : removedEdges) {
|
||||||
|
graph.removeEdge(edge[0], edge[1]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return removedEdges;
|
return removedEdges;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void addRemovedEdges(SimpleWeightedGraph<Integer, DefaultWeightedEdge> graph,
|
static void addRemovedEdges(SimpleWeightedGraph<Integer, DefaultWeightedEdge> graph,
|
||||||
List<Integer[]> removedEdges) {
|
List<Integer[]> removedEdges) {
|
||||||
for (Integer[] edge : removedEdges) {
|
for (Integer[] edge : removedEdges) {
|
||||||
DefaultWeightedEdge e = graph.addEdge(edge[0], edge[1]);
|
DefaultWeightedEdge e = graph.addEdge(edge[0], edge[1]);
|
||||||
|
|||||||
@@ -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() {
|
||||||
|
|||||||
@@ -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() {
|
||||||
|
|
||||||
@@ -26,6 +27,7 @@ public class InteractiveInterface {
|
|||||||
//Need to re-do the CDR3/CDR1 matching to correspond to new pattern
|
//Need to re-do the CDR3/CDR1 matching to correspond to new pattern
|
||||||
//System.out.println("5) Generate CDR3/CDR1 occupancy graph");
|
//System.out.println("5) Generate CDR3/CDR1 occupancy graph");
|
||||||
//System.out.println("6) Simulate CDR3/CDR1 T cell matching");
|
//System.out.println("6) Simulate CDR3/CDR1 T cell matching");
|
||||||
|
System.out.println("8) Options");
|
||||||
System.out.println("9) About/Acknowledgments");
|
System.out.println("9) About/Acknowledgments");
|
||||||
System.out.println("0) Exit");
|
System.out.println("0) Exit");
|
||||||
try {
|
try {
|
||||||
@@ -36,9 +38,10 @@ public class InteractiveInterface {
|
|||||||
case 3 -> makeCDR3Graph();
|
case 3 -> makeCDR3Graph();
|
||||||
case 4 -> matchCDR3s();
|
case 4 -> matchCDR3s();
|
||||||
//case 6 -> matchCellsCDR1();
|
//case 6 -> matchCellsCDR1();
|
||||||
|
case 8 -> mainOptions();
|
||||||
case 9 -> acknowledge();
|
case 9 -> acknowledge();
|
||||||
case 0 -> quit = true;
|
case 0 -> quit = true;
|
||||||
default -> throw new InputMismatchException("Invalid input.");
|
default -> System.out.println("Invalid input.");
|
||||||
}
|
}
|
||||||
} catch (InputMismatchException | IOException ex) {
|
} catch (InputMismatchException | IOException ex) {
|
||||||
System.out.println(ex);
|
System.out.println(ex);
|
||||||
@@ -73,9 +76,13 @@ 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.cacheCells()) {
|
||||||
|
BiGpairSEQ.setCellSampleInMemory(sample, 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,27 +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();
|
||||||
|
if(BiGpairSEQ.cacheCells()) {
|
||||||
|
BiGpairSEQ.setCellSampleInMemory(cells, 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");
|
System.out.println("Writing Sample Plate to file");
|
||||||
writer.writePlateFile();
|
writer.writePlateFile();
|
||||||
System.out.println("Sample Plate written to file: " + filename);
|
System.out.println("Sample Plate written to file: " + filename);
|
||||||
System.gc();
|
if(BiGpairSEQ.cachePlate()) {
|
||||||
|
BiGpairSEQ.setPlateInMemory(samplePlate, filename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -212,14 +268,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()) && BiGpairSEQ.getCellSampleInMemory() != null) {
|
||||||
|
cellSample = BiGpairSEQ.getCellSampleInMemory();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
System.out.println("Reading Cell Sample file: " + cellFile);
|
||||||
|
CellFileReader cellReader = new CellFileReader(cellFile);
|
||||||
|
cellSample = cellReader.getCellSample();
|
||||||
|
if(BiGpairSEQ.cacheCells()) {
|
||||||
|
BiGpairSEQ.setCellSampleInMemory(cellSample, 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 {
|
||||||
|
System.out.println("Reading Sample Plate file: " + plateFile);
|
||||||
|
PlateFileReader plateReader = new PlateFileReader(plateFile);
|
||||||
|
plate = new Plate(plateReader.getFilename(), plateReader.getWells());
|
||||||
|
if(BiGpairSEQ.cachePlate()) {
|
||||||
|
BiGpairSEQ.setPlateInMemory(plate, 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 +307,16 @@ 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();
|
if(BiGpairSEQ.cacheGraph()) {
|
||||||
|
BiGpairSEQ.setGraphInMemory(data, filename);
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -256,17 +338,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 +368,15 @@ 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.clearGraph();
|
data = BiGpairSEQ.getGraphInMemory();
|
||||||
//read object data from file
|
|
||||||
GraphDataObjectReader dataReader = new GraphDataObjectReader(graphFilename);
|
|
||||||
data = dataReader.getData();
|
|
||||||
//set new graph in memory and new filename
|
|
||||||
BiGpairSEQ.setGraph(data);
|
|
||||||
BiGpairSEQ.setGraphFilename(graphFilename);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
data = BiGpairSEQ.getGraph();
|
GraphDataObjectReader dataReader = new GraphDataObjectReader(graphFilename);
|
||||||
|
data = dataReader.getData();
|
||||||
|
if(BiGpairSEQ.cacheGraph()) {
|
||||||
|
BiGpairSEQ.setGraphInMemory(data, graphFilename);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///////
|
///////
|
||||||
@@ -403,6 +493,75 @@ public class InteractiveInterface {
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
private static void mainOptions(){
|
||||||
|
boolean backToMain = false;
|
||||||
|
while(!backToMain) {
|
||||||
|
System.out.println("\n--------------OPTIONS---------------");
|
||||||
|
System.out.println("1) Turn " + getOnOff(!BiGpairSEQ.cacheCells()) + " cell sample file caching");
|
||||||
|
System.out.println("2) Turn " + getOnOff(!BiGpairSEQ.cachePlate()) + " plate file caching");
|
||||||
|
System.out.println("3) Turn " + getOnOff(!BiGpairSEQ.cacheGraph()) + " graph/data file caching");
|
||||||
|
System.out.println("4) Maximum weight matching algorithm options");
|
||||||
|
System.out.println("0) Return to main menu");
|
||||||
|
try {
|
||||||
|
input = sc.nextInt();
|
||||||
|
switch (input) {
|
||||||
|
case 1 -> BiGpairSEQ.setCacheCells(!BiGpairSEQ.cacheCells());
|
||||||
|
case 2 -> BiGpairSEQ.setCachePlate(!BiGpairSEQ.cachePlate());
|
||||||
|
case 3 -> BiGpairSEQ.setCacheGraph(!BiGpairSEQ.cacheGraph());
|
||||||
|
case 4 -> algorithmOptions();
|
||||||
|
case 0 -> backToMain = true;
|
||||||
|
default -> System.out.println("Invalid input");
|
||||||
|
}
|
||||||
|
} catch (InputMismatchException ex) {
|
||||||
|
System.out.println(ex);
|
||||||
|
sc.next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function for printing menu items in mainOptions(). Returns a string based on the value of parameter.
|
||||||
|
*
|
||||||
|
* @param b - a boolean value
|
||||||
|
* @return String "on" if b is true, "off" if b is false
|
||||||
|
*/
|
||||||
|
private static String getOnOff(boolean b) {
|
||||||
|
if (b) { return "on";}
|
||||||
|
else { return "off"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void algorithmOptions(){
|
||||||
|
boolean backToOptions = false;
|
||||||
|
while(!backToOptions) {
|
||||||
|
System.out.println("\n---------ALGORITHM OPTIONS----------");
|
||||||
|
System.out.println("1) Use scaling algorithm by Duan and Su.");
|
||||||
|
System.out.println("2) Use LEDA book algorithm with Fibonacci heap priority queue");
|
||||||
|
System.out.println("3) Use LEDA book algorithm with pairing heap priority queue");
|
||||||
|
System.out.println("0) Return to Options menu");
|
||||||
|
try {
|
||||||
|
input = sc.nextInt();
|
||||||
|
switch (input) {
|
||||||
|
case 1 -> System.out.println("This option is not yet implemented. Choose another.");
|
||||||
|
case 2 -> {
|
||||||
|
BiGpairSEQ.setFibonacciHeap();
|
||||||
|
System.out.println("MWM algorithm set to LEDA with Fibonacci heap");
|
||||||
|
backToOptions = true;
|
||||||
|
}
|
||||||
|
case 3 -> {
|
||||||
|
BiGpairSEQ.setPairingHeap();
|
||||||
|
System.out.println("MWM algorithm set to LEDA with pairing heap");
|
||||||
|
backToOptions = true;
|
||||||
|
}
|
||||||
|
case 0 -> backToOptions = true;
|
||||||
|
default -> System.out.println("Invalid input");
|
||||||
|
}
|
||||||
|
} catch (InputMismatchException ex) {
|
||||||
|
System.out.println(ex);
|
||||||
|
sc.next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void acknowledge(){
|
private static void acknowledge(){
|
||||||
System.out.println("This program simulates BiGpairSEQ, a graph theory based adaptation");
|
System.out.println("This program simulates BiGpairSEQ, a graph theory based adaptation");
|
||||||
System.out.println("of the pairSEQ algorithm for pairing T cell receptor sequences.");
|
System.out.println("of the pairSEQ algorithm for pairing T cell receptor sequences.");
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
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;
|
||||||
import org.jgrapht.graph.DefaultWeightedEdge;
|
import org.jgrapht.graph.DefaultWeightedEdge;
|
||||||
import org.jgrapht.graph.SimpleWeightedGraph;
|
import org.jgrapht.graph.SimpleWeightedGraph;
|
||||||
|
import org.jheaps.tree.FibonacciHeap;
|
||||||
import org.jheaps.tree.PairingHeap;
|
import org.jheaps.tree.PairingHeap;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
@@ -14,8 +14,10 @@ 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 implements GraphModificationFunctions {
|
||||||
private static final int cdr3AlphaIndex = 0;
|
private static final int cdr3AlphaIndex = 0;
|
||||||
private static final int cdr3BetaIndex = 1;
|
private static final int cdr3BetaIndex = 1;
|
||||||
private static final int cdr1AlphaIndex = 2;
|
private static final int cdr1AlphaIndex = 2;
|
||||||
@@ -145,8 +147,8 @@ public class Simulator {
|
|||||||
Integer highThreshold, Integer maxOccupancyDifference,
|
Integer highThreshold, Integer maxOccupancyDifference,
|
||||||
Integer minOverlapPercent, boolean verbose) {
|
Integer minOverlapPercent, boolean verbose) {
|
||||||
Instant start = Instant.now();
|
Instant start = Instant.now();
|
||||||
//Integer arrays will contain TO VERTEX, FROM VERTEX, and WEIGHT (which I'll need to cast to double)
|
|
||||||
List<Integer[]> removedEdges = new ArrayList<>();
|
List<Integer[]> removedEdges = new ArrayList<>();
|
||||||
|
boolean saveEdges = BiGpairSEQ.cacheGraph();
|
||||||
int numWells = data.getNumWells();
|
int numWells = data.getNumWells();
|
||||||
Integer alphaCount = data.getAlphaCount();
|
Integer alphaCount = data.getAlphaCount();
|
||||||
Integer betaCount = data.getBetaCount();
|
Integer betaCount = data.getBetaCount();
|
||||||
@@ -159,33 +161,50 @@ public class Simulator {
|
|||||||
|
|
||||||
//remove edges with weights outside given overlap thresholds, add those to removed edge list
|
//remove edges with weights outside given overlap thresholds, add those to removed edge list
|
||||||
if(verbose){System.out.println("Eliminating edges with weights outside overlap threshold values");}
|
if(verbose){System.out.println("Eliminating edges with weights outside overlap threshold values");}
|
||||||
removedEdges.addAll(GraphModificationFunctions.filterByOverlapThresholds(graph, lowThreshold, highThreshold));
|
removedEdges.addAll(GraphModificationFunctions.filterByOverlapThresholds(graph, lowThreshold, highThreshold, saveEdges));
|
||||||
if(verbose){System.out.println("Over- and under-weight edges removed");}
|
if(verbose){System.out.println("Over- and under-weight edges removed");}
|
||||||
|
|
||||||
//remove edges between vertices with too small an overlap size, add those to removed edge list
|
//remove edges between vertices with too small an overlap size, add those to removed edge list
|
||||||
if(verbose){System.out.println("Eliminating edges with weights less than " + minOverlapPercent.toString() +
|
if(verbose){System.out.println("Eliminating edges with weights less than " + minOverlapPercent.toString() +
|
||||||
" percent of vertex occupancy value.");}
|
" percent of vertex occupancy value.");}
|
||||||
removedEdges.addAll(GraphModificationFunctions.filterByOverlapPercent(graph, alphaWellCounts, betaWellCounts,
|
removedEdges.addAll(GraphModificationFunctions.filterByOverlapPercent(graph, alphaWellCounts, betaWellCounts,
|
||||||
plateVtoAMap, plateVtoBMap, minOverlapPercent));
|
plateVtoAMap, plateVtoBMap, minOverlapPercent, saveEdges));
|
||||||
if(verbose){System.out.println("Edges with weights too far below a vertex occupancy value removed");}
|
if(verbose){System.out.println("Edges with weights too far below a vertex occupancy value removed");}
|
||||||
|
|
||||||
//Filter by relative occupancy
|
//Filter by relative occupancy
|
||||||
if(verbose){System.out.println("Eliminating edges between vertices with occupancy difference > "
|
if(verbose){System.out.println("Eliminating edges between vertices with occupancy difference > "
|
||||||
+ maxOccupancyDifference);}
|
+ maxOccupancyDifference);}
|
||||||
removedEdges.addAll(GraphModificationFunctions.filterByRelativeOccupancy(graph, alphaWellCounts, betaWellCounts,
|
removedEdges.addAll(GraphModificationFunctions.filterByRelativeOccupancy(graph, alphaWellCounts, betaWellCounts,
|
||||||
plateVtoAMap, plateVtoBMap, maxOccupancyDifference));
|
plateVtoAMap, plateVtoBMap, maxOccupancyDifference, saveEdges));
|
||||||
if(verbose){System.out.println("Edges between vertices of with excessively different occupancy values " +
|
if(verbose){System.out.println("Edges between vertices of with excessively different occupancy values " +
|
||||||
"removed");}
|
"removed");}
|
||||||
|
|
||||||
//Find Maximum Weighted Matching
|
//Find Maximum Weighted Matching
|
||||||
//using jheaps library class PairingHeap for improved efficiency
|
//using jheaps library class PairingHeap for improved efficiency
|
||||||
if(verbose){System.out.println("Finding maximum weighted matching");}
|
if(verbose){System.out.println("Finding maximum weighted matching");}
|
||||||
//Attempting to use addressable heap to improve performance
|
MaximumWeightBipartiteMatching maxWeightMatching;
|
||||||
MaximumWeightBipartiteMatching maxWeightMatching =
|
//Use correct heap type for priority queue
|
||||||
new MaximumWeightBipartiteMatching(graph,
|
String heapType = BiGpairSEQ.getPriorityQueueHeapType();
|
||||||
|
switch (heapType) {
|
||||||
|
case "PAIRING" -> {
|
||||||
|
maxWeightMatching = new MaximumWeightBipartiteMatching(graph,
|
||||||
plateVtoAMap.keySet(),
|
plateVtoAMap.keySet(),
|
||||||
plateVtoBMap.keySet(),
|
plateVtoBMap.keySet(),
|
||||||
i -> new PairingHeap(Comparator.naturalOrder()));
|
i -> new PairingHeap(Comparator.naturalOrder()));
|
||||||
|
}
|
||||||
|
case "FIBONACCI" -> {
|
||||||
|
maxWeightMatching = new MaximumWeightBipartiteMatching(graph,
|
||||||
|
plateVtoAMap.keySet(),
|
||||||
|
plateVtoBMap.keySet(),
|
||||||
|
i -> new FibonacciHeap(Comparator.naturalOrder()));
|
||||||
|
}
|
||||||
|
default -> {
|
||||||
|
maxWeightMatching = new MaximumWeightBipartiteMatching(graph,
|
||||||
|
plateVtoAMap.keySet(),
|
||||||
|
plateVtoBMap.keySet());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//get the matching
|
||||||
MatchingAlgorithm.Matching<String, DefaultWeightedEdge> graphMatching = maxWeightMatching.getMatching();
|
MatchingAlgorithm.Matching<String, DefaultWeightedEdge> graphMatching = maxWeightMatching.getMatching();
|
||||||
if(verbose){System.out.println("Matching completed");}
|
if(verbose){System.out.println("Matching completed");}
|
||||||
Instant stop = Instant.now();
|
Instant stop = Instant.now();
|
||||||
@@ -247,10 +266,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 +295,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));
|
||||||
@@ -285,10 +310,11 @@ public class Simulator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//put the removed edges back on the graph
|
if(saveEdges) {
|
||||||
System.out.println("Restoring removed edges to graph.");
|
//put the removed edges back on the graph
|
||||||
GraphModificationFunctions.addRemovedEdges(graph, removedEdges);
|
System.out.println("Restoring removed edges to graph.");
|
||||||
|
GraphModificationFunctions.addRemovedEdges(graph, removedEdges);
|
||||||
|
}
|
||||||
//return MatchingResult object
|
//return MatchingResult object
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user