by-hand merge of needed code from custom vertex branch

This commit is contained in:
eugenefischer
2022-09-21 16:48:26 -05:00
parent 3ba305abdb
commit 29b844afd2
6 changed files with 277 additions and 175 deletions

View File

@@ -3,8 +3,9 @@ import org.jgrapht.graph.SimpleWeightedGraph;
import org.jgrapht.nio.Attribute; import org.jgrapht.nio.Attribute;
import org.jgrapht.nio.AttributeType; import org.jgrapht.nio.AttributeType;
import org.jgrapht.nio.DefaultAttribute; import org.jgrapht.nio.DefaultAttribute;
import org.jgrapht.nio.dot.DOTExporter;
import org.jgrapht.nio.graphml.GraphMLExporter; import org.jgrapht.nio.graphml.GraphMLExporter;
import org.jgrapht.nio.graphml.GraphMLExporter.AttributeCategory;
import org.w3c.dom.Attr;
import java.io.BufferedWriter; import java.io.BufferedWriter;
import java.io.IOException; import java.io.IOException;
@@ -12,14 +13,14 @@ import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.StandardOpenOption; import java.nio.file.StandardOpenOption;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
public class GraphMLFileWriter { public class GraphMLFileWriter {
String filename; String filename;
SimpleWeightedGraph graph;
GraphWithMapData data; GraphWithMapData data;
Map<String, Attribute> graphAttributes;
public GraphMLFileWriter(String filename, GraphWithMapData data) { public GraphMLFileWriter(String filename, GraphWithMapData data) {
if(!filename.matches(".*\\.graphml")){ if(!filename.matches(".*\\.graphml")){
@@ -27,52 +28,61 @@ public class GraphMLFileWriter {
} }
this.filename = filename; this.filename = filename;
this.data = data; this.data = data;
this.graph = data.getGraph();
graphAttributes = createGraphAttributes();
} }
// public void writeGraphToFile() { public GraphMLFileWriter(String filename, SimpleWeightedGraph<Vertex, DefaultWeightedEdge> graph) {
// try(BufferedWriter writer = Files.newBufferedWriter(Path.of(filename), StandardOpenOption.CREATE_NEW); if(!filename.matches(".*\\.graphml")){
// ){ filename = filename + ".graphml";
// GraphMLExporter<SimpleWeightedGraph, BufferedWriter> exporter = new GraphMLExporter<>(); }
// exporter.exportGraph(graph, writer); this.filename = filename;
// } catch(IOException ex){ this.graph = graph;
// System.out.println("Could not make new file named "+filename); }
// System.err.println(ex);
// } private Map<String, Attribute> createGraphAttributes(){
// } Map<String, Attribute> ga = new HashMap<>();
//Sample plate filename
ga.put("sample plate filename", DefaultAttribute.createAttribute(data.getSourceFilename()));
// Number of wells
ga.put("well count", DefaultAttribute.createAttribute(data.getNumWells().toString()));
//Well populations
Integer[] wellPopulations = data.getWellPopulations();
StringBuilder populationsStringBuilder = new StringBuilder();
populationsStringBuilder.append(wellPopulations[0].toString());
for(int i = 1; i < wellPopulations.length; i++){
populationsStringBuilder.append(", ");
populationsStringBuilder.append(wellPopulations[i].toString());
}
String wellPopulationsString = populationsStringBuilder.toString();
ga.put("well populations", DefaultAttribute.createAttribute(wellPopulationsString));
return ga;
}
public void writeGraphToFile() { public void writeGraphToFile() {
SimpleWeightedGraph graph = data.getGraph();
Map<Integer, Integer> vertexToAlphaMap = data.getPlateVtoAMap();
Map<Integer, Integer> vertexToBetaMap = data.getPlateVtoBMap();
Map<Integer, Integer> alphaOccs = data.getAlphaWellCounts();
Map<Integer, Integer> betaOccs = data.getBetaWellCounts();
try(BufferedWriter writer = Files.newBufferedWriter(Path.of(filename), StandardOpenOption.CREATE_NEW); try(BufferedWriter writer = Files.newBufferedWriter(Path.of(filename), StandardOpenOption.CREATE_NEW);
){ ){
//create exporter. Let the vertex labels be the unique ids for the vertices //create exporter. Let the vertex labels be the unique ids for the vertices
GraphMLExporter<Integer, SimpleWeightedGraph<Vertex, DefaultWeightedEdge>> exporter = new GraphMLExporter<>(v -> v.toString()); GraphMLExporter<Vertex, SimpleWeightedGraph<Vertex, DefaultWeightedEdge>> exporter = new GraphMLExporter<>(v -> v.getVertexLabel().toString());
//set to export weights //set to export weights
exporter.setExportEdgeWeights(true); exporter.setExportEdgeWeights(true);
//Set graph attributes
exporter.setGraphAttributeProvider( () -> graphAttributes);
//set type, sequence, and occupancy attributes for each vertex //set type, sequence, and occupancy attributes for each vertex
exporter.setVertexAttributeProvider( v -> { exporter.setVertexAttributeProvider( v -> {
Map<String, Attribute> attributes = new HashMap<>(); Map<String, Attribute> attributes = new HashMap<>();
if(vertexToAlphaMap.containsKey(v)) { attributes.put("type", DefaultAttribute.createAttribute(v.getType().name()));
attributes.put("type", DefaultAttribute.createAttribute("CDR3 Alpha")); attributes.put("sequence", DefaultAttribute.createAttribute(v.getSequence()));
attributes.put("sequence", DefaultAttribute.createAttribute(vertexToAlphaMap.get(v))); attributes.put("occupancy", DefaultAttribute.createAttribute(v.getOccupancy()));
attributes.put("occupancy", DefaultAttribute.createAttribute(
alphaOccs.get(vertexToAlphaMap.get(v))));
}
else if(vertexToBetaMap.containsKey(v)) {
attributes.put("type", DefaultAttribute.createAttribute("CDR3 Beta"));
attributes.put("sequence", DefaultAttribute.createAttribute(vertexToBetaMap.get(v)));
attributes.put("occupancy", DefaultAttribute.createAttribute(
betaOccs.get(vertexToBetaMap.get(v))));
}
return attributes; return attributes;
}); });
//register the attributes //register the attributes
exporter.registerAttribute("type", GraphMLExporter.AttributeCategory.NODE, AttributeType.STRING); for(String s : graphAttributes.keySet()) {
exporter.registerAttribute("sequence", GraphMLExporter.AttributeCategory.NODE, AttributeType.STRING); exporter.registerAttribute(s, AttributeCategory.GRAPH, AttributeType.STRING);
exporter.registerAttribute("occupancy", GraphMLExporter.AttributeCategory.NODE, AttributeType.STRING); }
exporter.registerAttribute("type", AttributeCategory.NODE, AttributeType.STRING);
exporter.registerAttribute("sequence", AttributeCategory.NODE, AttributeType.STRING);
exporter.registerAttribute("occupancy", AttributeCategory.NODE, AttributeType.STRING);
//export the graph //export the graph
exporter.exportGraph(graph, writer); exporter.exportGraph(graph, writer);
} catch(IOException ex){ } catch(IOException ex){
@@ -81,4 +91,3 @@ public class GraphMLFileWriter {
} }
} }
} }

View File

@@ -2,23 +2,25 @@ import org.jgrapht.graph.DefaultWeightedEdge;
import org.jgrapht.graph.SimpleWeightedGraph; import org.jgrapht.graph.SimpleWeightedGraph;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
public interface GraphModificationFunctions { public interface GraphModificationFunctions {
//remove over- and under-weight edges //remove over- and under-weight edges
static List<Integer[]> filterByOverlapThresholds(SimpleWeightedGraph<Integer, DefaultWeightedEdge> graph, static Map<Vertex[], Integer> filterByOverlapThresholds(SimpleWeightedGraph<Vertex, DefaultWeightedEdge> graph,
int low, int high, boolean saveEdges) { int low, int high, boolean saveEdges) {
List<Integer[]> removedEdges = new ArrayList<>(); Map<Vertex[], Integer> removedEdges = new HashMap<>();
//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)) {
if(saveEdges) { if(saveEdges) {
Integer source = graph.getEdgeSource(e); Vertex source = graph.getEdgeSource(e);
Integer target = graph.getEdgeTarget(e); Vertex target = graph.getEdgeTarget(e);
Integer weight = (int) graph.getEdgeWeight(e); Integer weight = (int) graph.getEdgeWeight(e);
Integer[] edge = {source, target, weight}; Vertex[] edge = {source, target};
removedEdges.add(edge); removedEdges.put(edge, weight);
} }
else { else {
graph.setEdgeWeight(e, 0.0); graph.setEdgeWeight(e, 0.0);
@@ -26,7 +28,7 @@ public interface GraphModificationFunctions {
} }
} }
if(saveEdges) { if(saveEdges) {
for (Integer[] edge : removedEdges) { for (Vertex[] edge : removedEdges.keySet()) {
graph.removeEdge(edge[0], edge[1]); graph.removeEdge(edge[0], edge[1]);
} }
} }
@@ -34,23 +36,19 @@ public interface GraphModificationFunctions {
} }
//Remove edges for pairs with large occupancy discrepancy //Remove edges for pairs with large occupancy discrepancy
static List<Integer[]> filterByRelativeOccupancy(SimpleWeightedGraph<Integer, DefaultWeightedEdge> graph, static Map<Vertex[], Integer> filterByRelativeOccupancy(SimpleWeightedGraph<Vertex, DefaultWeightedEdge> graph,
Map<Integer, Integer> alphaWellCounts,
Map<Integer, Integer> betaWellCounts,
Map<Integer, Integer> plateVtoAMap,
Map<Integer, Integer> plateVtoBMap,
Integer maxOccupancyDifference, boolean saveEdges) { Integer maxOccupancyDifference, boolean saveEdges) {
List<Integer[]> removedEdges = new ArrayList<>(); Map<Vertex[], Integer> removedEdges = new HashMap<>();
for (DefaultWeightedEdge e : graph.edgeSet()) { for (DefaultWeightedEdge e : graph.edgeSet()) {
Integer alphaOcc = alphaWellCounts.get(plateVtoAMap.get(graph.getEdgeSource(e))); Integer alphaOcc = graph.getEdgeSource(e).getOccupancy();
Integer betaOcc = betaWellCounts.get(plateVtoBMap.get(graph.getEdgeTarget(e))); Integer betaOcc = graph.getEdgeTarget(e).getOccupancy();
if (Math.abs(alphaOcc - betaOcc) >= maxOccupancyDifference) { if (Math.abs(alphaOcc - betaOcc) >= maxOccupancyDifference) {
if (saveEdges) { if (saveEdges) {
Integer source = graph.getEdgeSource(e); Vertex source = graph.getEdgeSource(e);
Integer target = graph.getEdgeTarget(e); Vertex target = graph.getEdgeTarget(e);
Integer weight = (int) graph.getEdgeWeight(e); Integer weight = (int) graph.getEdgeWeight(e);
Integer[] edge = {source, target, weight}; Vertex[] edge = {source, target};
removedEdges.add(edge); removedEdges.put(edge, weight);
} }
else { else {
graph.setEdgeWeight(e, 0.0); graph.setEdgeWeight(e, 0.0);
@@ -58,7 +56,7 @@ public interface GraphModificationFunctions {
} }
} }
if(saveEdges) { if(saveEdges) {
for (Integer[] edge : removedEdges) { for (Vertex[] edge : removedEdges.keySet()) {
graph.removeEdge(edge[0], edge[1]); graph.removeEdge(edge[0], edge[1]);
} }
} }
@@ -66,26 +64,22 @@ public interface GraphModificationFunctions {
} }
//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
static List<Integer[]> filterByOverlapPercent(SimpleWeightedGraph<Integer, DefaultWeightedEdge> graph, static Map<Vertex[], Integer> filterByOverlapPercent(SimpleWeightedGraph<Vertex, DefaultWeightedEdge> graph,
Map<Integer, Integer> alphaWellCounts,
Map<Integer, Integer> betaWellCounts,
Map<Integer, Integer> plateVtoAMap,
Map<Integer, Integer> plateVtoBMap,
Integer minOverlapPercent, Integer minOverlapPercent,
boolean saveEdges) { boolean saveEdges) {
List<Integer[]> removedEdges = new ArrayList<>(); Map<Vertex[], Integer> removedEdges = new HashMap<>();
for (DefaultWeightedEdge e : graph.edgeSet()) { for (DefaultWeightedEdge e : graph.edgeSet()) {
Integer alphaOcc = alphaWellCounts.get(plateVtoAMap.get(graph.getEdgeSource(e))); Integer alphaOcc = graph.getEdgeSource(e).getOccupancy();
Integer betaOcc = betaWellCounts.get(plateVtoBMap.get(graph.getEdgeTarget(e))); Integer betaOcc = graph.getEdgeTarget(e).getOccupancy();
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)) {
if(saveEdges) { if (saveEdges) {
Integer source = graph.getEdgeSource(e); Vertex source = graph.getEdgeSource(e);
Integer target = graph.getEdgeTarget(e); Vertex target = graph.getEdgeTarget(e);
Integer intWeight = (int) graph.getEdgeWeight(e); Integer intWeight = (int) graph.getEdgeWeight(e);
Integer[] edge = {source, target, intWeight}; Vertex[] edge = {source, target};
removedEdges.add(edge); removedEdges.put(edge, intWeight);
} }
else { else {
graph.setEdgeWeight(e, 0.0); graph.setEdgeWeight(e, 0.0);
@@ -93,18 +87,18 @@ public interface GraphModificationFunctions {
} }
} }
if(saveEdges) { if(saveEdges) {
for (Integer[] edge : removedEdges) { for (Vertex[] edge : removedEdges.keySet()) {
graph.removeEdge(edge[0], edge[1]); graph.removeEdge(edge[0], edge[1]);
} }
} }
return removedEdges; return removedEdges;
} }
static void addRemovedEdges(SimpleWeightedGraph<Integer, DefaultWeightedEdge> graph, static void addRemovedEdges(SimpleWeightedGraph<Vertex, DefaultWeightedEdge> graph,
List<Integer[]> removedEdges) { Map<Vertex[], Integer> removedEdges) {
for (Integer[] edge : removedEdges) { for (Vertex[] edge : removedEdges.keySet()) {
DefaultWeightedEdge e = graph.addEdge(edge[0], edge[1]); DefaultWeightedEdge e = graph.addEdge(edge[0], edge[1]);
graph.setEdgeWeight(e, (double) edge[2]); graph.setEdgeWeight(e, removedEdges.get(edge));
} }
} }

View File

@@ -15,32 +15,33 @@ public class GraphWithMapData implements java.io.Serializable {
private Integer alphaCount; private Integer alphaCount;
private Integer betaCount; private Integer betaCount;
private final Map<Integer, Integer> distCellsMapAlphaKey; private final Map<Integer, Integer> distCellsMapAlphaKey;
private final Map<Integer, Integer> plateVtoAMap; // private final Map<Integer, Integer> plateVtoAMap;
private final Map<Integer, Integer> plateVtoBMap; // private final Map<Integer, Integer> plateVtoBMap;
private final Map<Integer, Integer> plateAtoVMap; // private final Map<Integer, Integer> plateAtoVMap;
private final Map<Integer, Integer> plateBtoVMap; // private final Map<Integer, Integer> plateBtoVMap;
private final Map<Integer, Integer> alphaWellCounts; // private final Map<Integer, Integer> alphaWellCounts;
private final Map<Integer, Integer> betaWellCounts; // private final Map<Integer, Integer> betaWellCounts;
private final Duration time; private final Duration time;
public GraphWithMapData(SimpleWeightedGraph graph, Integer numWells, Integer[] wellConcentrations, public GraphWithMapData(SimpleWeightedGraph graph, Integer numWells, Integer[] wellConcentrations,
Integer alphaCount, Integer betaCount, Map<Integer, Integer> distCellsMapAlphaKey, Duration time){
Map<Integer, Integer> distCellsMapAlphaKey, Map<Integer, Integer> plateVtoAMap,
Map<Integer,Integer> plateVtoBMap, Map<Integer, Integer> plateAtoVMap, // Map<Integer, Integer> plateVtoAMap, Integer alphaCount, Integer betaCount,
Map<Integer, Integer> plateBtoVMap, Map<Integer, Integer> alphaWellCounts, // Map<Integer,Integer> plateVtoBMap, Map<Integer, Integer> plateAtoVMap,
Map<Integer, Integer> betaWellCounts, Duration time) { // Map<Integer, Integer> plateBtoVMap, Map<Integer, Integer> alphaWellCounts,
// Map<Integer, Integer> betaWellCounts,) {
this.graph = graph; this.graph = graph;
this.numWells = numWells; this.numWells = numWells;
this.wellPopulations = wellConcentrations; this.wellPopulations = wellConcentrations;
this.alphaCount = alphaCount; this.alphaCount = alphaCount;
this.betaCount = betaCount; this.betaCount = betaCount;
this.distCellsMapAlphaKey = distCellsMapAlphaKey; this.distCellsMapAlphaKey = distCellsMapAlphaKey;
this.plateVtoAMap = plateVtoAMap; // this.plateVtoAMap = plateVtoAMap;
this.plateVtoBMap = plateVtoBMap; // this.plateVtoBMap = plateVtoBMap;
this.plateAtoVMap = plateAtoVMap; // this.plateAtoVMap = plateAtoVMap;
this.plateBtoVMap = plateBtoVMap; // this.plateBtoVMap = plateBtoVMap;
this.alphaWellCounts = alphaWellCounts; // this.alphaWellCounts = alphaWellCounts;
this.betaWellCounts = betaWellCounts; // this.betaWellCounts = betaWellCounts;
this.time = time; this.time = time;
} }
@@ -56,41 +57,41 @@ public class GraphWithMapData implements java.io.Serializable {
return wellPopulations; return wellPopulations;
} }
public Integer getAlphaCount() { // public Integer getAlphaCount() {
return alphaCount; // return alphaCount;
} // }
//
public Integer getBetaCount() { // public Integer getBetaCount() {
return betaCount; // return betaCount;
} // }
public Map<Integer, Integer> getDistCellsMapAlphaKey() { public Map<Integer, Integer> getDistCellsMapAlphaKey() {
return distCellsMapAlphaKey; return distCellsMapAlphaKey;
} }
public Map<Integer, Integer> getPlateVtoAMap() { // public Map<Integer, Integer> getPlateVtoAMap() {
return plateVtoAMap; // return plateVtoAMap;
} // }
//
public Map<Integer, Integer> getPlateVtoBMap() { // public Map<Integer, Integer> getPlateVtoBMap() {
return plateVtoBMap; // return plateVtoBMap;
} // }
//
public Map<Integer, Integer> getPlateAtoVMap() { // public Map<Integer, Integer> getPlateAtoVMap() {
return plateAtoVMap; // return plateAtoVMap;
} // }
//
public Map<Integer, Integer> getPlateBtoVMap() { // public Map<Integer, Integer> getPlateBtoVMap() {
return plateBtoVMap; // return plateBtoVMap;
} // }
//
public Map<Integer, Integer> getAlphaWellCounts() { // public Map<Integer, Integer> getAlphaWellCounts() {
return alphaWellCounts; // return alphaWellCounts;
} // }
//
public Map<Integer, Integer> getBetaWellCounts() { // public Map<Integer, Integer> getBetaWellCounts() {
return betaWellCounts; // return betaWellCounts;
} // }
public Duration getTime() { public Duration getTime() {
return time; return time;

View File

@@ -0,0 +1,8 @@
//enum for tagging types of sequences
//Listed in order that they appear in a cell array, so ordinal() method will return correct index
public enum SequenceType {
CDR3_ALPHA,
CDR3_BETA,
CDR1_ALPHA,
CDR1_BETA
}

View File

@@ -18,29 +18,29 @@ 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 implements GraphModificationFunctions { public class Simulator implements GraphModificationFunctions {
private static final int cdr3AlphaIndex = 0;
private static final int cdr3BetaIndex = 1;
private static final int cdr1AlphaIndex = 2;
private static final int cdr1BetaIndex = 3;
//Make the graph needed for matching CDR3s //Make the graph needed for matching sequences.
//sourceVertexIndices and targetVertexIndices are indices within the cell to use as for the two sets of vertices
//in the bipartite graph. "Source" and "target" are JGraphT terms for the two vertices an edge touches,
//even if not directed.
public static GraphWithMapData makeGraph(CellSample cellSample, Plate samplePlate, boolean verbose) { public static GraphWithMapData makeGraph(CellSample cellSample, Plate samplePlate, boolean verbose) {
Instant start = Instant.now(); Instant start = Instant.now();
List<Integer[]> distinctCells = cellSample.getCells(); List<Integer[]> distinctCells = cellSample.getCells();
int[] alphaIndex = {cdr3AlphaIndex}; int[] alphaIndices = {SequenceType.CDR3_ALPHA.ordinal()};
int[] betaIndex = {cdr3BetaIndex}; int[] betaIndices = {SequenceType.CDR3_BETA.ordinal()};
int numWells = samplePlate.getSize(); int numWells = samplePlate.getSize();
if(verbose){System.out.println("Making cell maps");} if(verbose){System.out.println("Making cell maps");}
//HashMap keyed to Alphas, values Betas //HashMap keyed to Alphas, values Betas
Map<Integer, Integer> distCellsMapAlphaKey = makeSequenceToSequenceMap(distinctCells, cdr3AlphaIndex, cdr3BetaIndex); Map<Integer, Integer> distCellsMapAlphaKey = makeSequenceToSequenceMap(distinctCells, 0, 1);
if(verbose){System.out.println("Cell maps made");} if(verbose){System.out.println("Cell maps made");}
if(verbose){System.out.println("Making well maps");} if(verbose){System.out.println("Making well maps");}
Map<Integer, Integer> allAlphas = samplePlate.assayWellsSequenceS(alphaIndex);
Map<Integer, Integer> allBetas = samplePlate.assayWellsSequenceS(betaIndex); Map<Integer, Integer> allAlphas = samplePlate.assayWellsSequenceS(alphaIndices);
Map<Integer, Integer> allBetas = samplePlate.assayWellsSequenceS(betaIndices);
int alphaCount = allAlphas.size(); int alphaCount = allAlphas.size();
if(verbose){System.out.println("All alphas count: " + alphaCount);} if(verbose){System.out.println("All alphas count: " + alphaCount);}
int betaCount = allBetas.size(); int betaCount = allBetas.size();
@@ -80,29 +80,40 @@ public class Simulator implements GraphModificationFunctions {
//(technically this is only 1/4 of an adjacency matrix, but that's all you need //(technically this is only 1/4 of an adjacency matrix, but that's all you need
//for a bipartite graph, and all the SimpleWeightedBipartiteGraphMatrixGenerator class expects.) //for a bipartite graph, and all the SimpleWeightedBipartiteGraphMatrixGenerator class expects.)
if(verbose){System.out.println("Creating adjacency matrix");} if(verbose){System.out.println("Creating adjacency matrix");}
//Count how many wells each alpha appears in //Count how many wells each alpha sequence appears in
Map<Integer, Integer> alphaWellCounts = new HashMap<>(); Map<Integer, Integer> alphaWellCounts = new HashMap<>();
//count how many wells each beta appears in //count how many wells each beta sequence appears in
Map<Integer, Integer> betaWellCounts = new HashMap<>(); Map<Integer, Integer> betaWellCounts = new HashMap<>();
//the adjacency matrix to be used by the graph generator //the adjacency matrix to be used by the graph generator
double[][] weights = new double[plateVtoAMap.size()][plateVtoBMap.size()]; double[][] weights = new double[plateVtoAMap.size()][plateVtoBMap.size()];
countSequencesAndFillMatrix(samplePlate, allAlphas, allBetas, plateAtoVMap, countSequencesAndFillMatrix(samplePlate, allAlphas, allBetas, plateAtoVMap,
plateBtoVMap, alphaIndex, betaIndex, alphaWellCounts, betaWellCounts, weights); plateBtoVMap, alphaIndices, betaIndices, alphaWellCounts, betaWellCounts, weights);
if(verbose){System.out.println("Matrix created");} if(verbose){System.out.println("Matrix created");}
//create bipartite graph //create bipartite graph
if(verbose){System.out.println("Creating graph");} if(verbose){System.out.println("Creating graph");}
//the graph object //the graph object
SimpleWeightedGraph<Integer, DefaultWeightedEdge> graph = SimpleWeightedGraph<Vertex, DefaultWeightedEdge> graph =
new SimpleWeightedGraph<>(DefaultWeightedEdge.class); new SimpleWeightedGraph<>(DefaultWeightedEdge.class);
//the graph generator //the graph generator
SimpleWeightedBipartiteGraphMatrixGenerator graphGenerator = new SimpleWeightedBipartiteGraphMatrixGenerator(); SimpleWeightedBipartiteGraphMatrixGenerator graphGenerator = new SimpleWeightedBipartiteGraphMatrixGenerator();
//the list of alpha vertices //the list of alpha vertices
List<Integer> alphaVertices = new ArrayList<>(plateVtoAMap.keySet()); //This will work because LinkedHashMap preserves order of entry //List<Integer> alphaVertices = new ArrayList<>(plateVtoAMap.keySet()); //This will work because LinkedHashMap preserves order of entry
List<Vertex> alphaVertices = new ArrayList<>();
//start with map of all alphas mapped to vertex values, get occupancy from the alphaWellCounts map
for (Integer seq : plateAtoVMap.keySet()) {
Vertex alphaVertex = new Vertex(SequenceType.CDR3_ALPHA, seq, alphaWellCounts.get(seq), plateAtoVMap.get(seq));
alphaVertices.add(alphaVertex);
}
graphGenerator.first(alphaVertices); graphGenerator.first(alphaVertices);
//the list of beta vertices //the list of beta vertices
List<Integer> betaVertices = new ArrayList<>(plateVtoBMap.keySet()); //List<Integer> betaVertices = new ArrayList<>(plateVtoBMap.keySet());//This will work because LinkedHashMap preserves order of entry
graphGenerator.second(betaVertices); //This will work because LinkedHashMap preserves order of entry List<Vertex> betaVertices = new ArrayList<>();
for (Integer seq : plateBtoVMap.keySet()) {
Vertex betaVertex = new Vertex(SequenceType.CDR3_BETA, seq, betaWellCounts.get(seq), plateBtoVMap.get(seq));
betaVertices.add(betaVertex);
}
graphGenerator.second(betaVertices);
//use adjacency matrix of weight created previously //use adjacency matrix of weight created previously
graphGenerator.weights(weights); graphGenerator.weights(weights);
graphGenerator.generateGraph(graph); graphGenerator.generateGraph(graph);
@@ -112,9 +123,7 @@ public class Simulator implements GraphModificationFunctions {
Duration time = Duration.between(start, stop); Duration time = Duration.between(start, stop);
//create GraphWithMapData object //create GraphWithMapData object
GraphWithMapData output = new GraphWithMapData(graph, numWells, samplePlate.getPopulations(), alphaCount, betaCount, GraphWithMapData output = new GraphWithMapData(graph, numWells, samplePlate.getPopulations(), distCellsMapAlphaKey, time);
distCellsMapAlphaKey, plateVtoAMap, plateVtoBMap, plateAtoVMap,
plateBtoVMap, alphaWellCounts, betaWellCounts, time);
//Set source file name in graph to name of sample plate //Set source file name in graph to name of sample plate
output.setSourceFilename(samplePlate.getFilename()); output.setSourceFilename(samplePlate.getFilename());
//return GraphWithMapData object //return GraphWithMapData object
@@ -126,39 +135,46 @@ public class Simulator implements GraphModificationFunctions {
Integer highThreshold, Integer maxOccupancyDifference, Integer highThreshold, Integer maxOccupancyDifference,
Integer minOverlapPercent, boolean verbose) { Integer minOverlapPercent, boolean verbose) {
Instant start = Instant.now(); Instant start = Instant.now();
List<Integer[]> removedEdges = new ArrayList<>(); SimpleWeightedGraph<Vertex, DefaultWeightedEdge> graph = data.getGraph();
Map<Vertex[], Integer> removedEdges = new HashMap<>();
boolean saveEdges = BiGpairSEQ.cacheGraph(); 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();
Map<Integer, Integer> distCellsMapAlphaKey = data.getDistCellsMapAlphaKey(); Map<Integer, Integer> distCellsMapAlphaKey = data.getDistCellsMapAlphaKey();
Map<Integer, Integer> plateVtoAMap = data.getPlateVtoAMap(); Set<Vertex> alphas = new HashSet<>();
Map<Integer, Integer> plateVtoBMap = data.getPlateVtoBMap(); Set<Vertex> betas = new HashSet<>();
Map<Integer, Integer> alphaWellCounts = data.getAlphaWellCounts(); for(Vertex v: graph.vertexSet()) {
Map<Integer, Integer> betaWellCounts = data.getBetaWellCounts(); if (SequenceType.CDR3_ALPHA.equals(v.getType())){
SimpleWeightedGraph<Integer, DefaultWeightedEdge> graph = data.getGraph(); alphas.add(v);
}
else {
betas.add(v);
}
}
Integer alphaCount = alphas.size();
Integer betaCount = betas.size();
//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, saveEdges)); removedEdges.putAll(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.putAll(GraphModificationFunctions.filterByOverlapPercent(graph, minOverlapPercent, saveEdges));
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.putAll(GraphModificationFunctions.filterByRelativeOccupancy(graph, maxOccupancyDifference, saveEdges));
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
if(verbose){System.out.println("Finding maximum weighted matching");} if(verbose){System.out.println("Finding maximum weighted matching");}
MaximumWeightBipartiteMatching maxWeightMatching; MaximumWeightBipartiteMatching maxWeightMatching;
//Use correct heap type for priority queue //Use correct heap type for priority queue
@@ -166,20 +182,20 @@ public class Simulator implements GraphModificationFunctions {
switch (heapType) { switch (heapType) {
case "PAIRING" -> { case "PAIRING" -> {
maxWeightMatching = new MaximumWeightBipartiteMatching(graph, maxWeightMatching = new MaximumWeightBipartiteMatching(graph,
plateVtoAMap.keySet(), alphas,
plateVtoBMap.keySet(), betas,
i -> new PairingHeap(Comparator.naturalOrder())); i -> new PairingHeap(Comparator.naturalOrder()));
} }
case "FIBONACCI" -> { case "FIBONACCI" -> {
maxWeightMatching = new MaximumWeightBipartiteMatching(graph, maxWeightMatching = new MaximumWeightBipartiteMatching(graph,
plateVtoAMap.keySet(), alphas,
plateVtoBMap.keySet(), betas,
i -> new FibonacciHeap(Comparator.naturalOrder())); i -> new FibonacciHeap(Comparator.naturalOrder()));
} }
default -> { default -> {
maxWeightMatching = new MaximumWeightBipartiteMatching(graph, maxWeightMatching = new MaximumWeightBipartiteMatching(graph,
plateVtoAMap.keySet(), alphas,
plateVtoBMap.keySet()); betas);
} }
} }
//get the matching //get the matching
@@ -209,11 +225,14 @@ public class Simulator implements GraphModificationFunctions {
Map<Integer, Integer> matchMap = new HashMap<>(); Map<Integer, Integer> matchMap = new HashMap<>();
while(weightIter.hasNext()) { while(weightIter.hasNext()) {
e = weightIter.next(); e = weightIter.next();
Integer source = graph.getEdgeSource(e); Vertex source = graph.getEdgeSource(e);
Integer target = graph.getEdgeTarget(e); Vertex target = graph.getEdgeTarget(e);
//Integer source = graph.getEdgeSource(e);
//Integer target = graph.getEdgeTarget(e);
//The match map is all matches found, not just true matches! //The match map is all matches found, not just true matches!
matchMap.put(plateVtoAMap.get(source), plateVtoBMap.get(target)); matchMap.put(source.getSequence(), target.getSequence());
check = plateVtoBMap.get(target).equals(distCellsMapAlphaKey.get(plateVtoAMap.get(source))); check = target.getSequence().equals(distCellsMapAlphaKey.get(source.getSequence()));
//check = plateVtoBMap.get(target).equals(distCellsMapAlphaKey.get(plateVtoAMap.get(source)));
if(check) { if(check) {
trueCount++; trueCount++;
} }
@@ -221,17 +240,19 @@ public class Simulator implements GraphModificationFunctions {
falseCount++; falseCount++;
} }
List<String> result = new ArrayList<>(); List<String> result = new ArrayList<>();
result.add(plateVtoAMap.get(source).toString()); //alpha sequence
result.add(source.getSequence().toString());
//alpha well count //alpha well count
result.add(alphaWellCounts.get(plateVtoAMap.get(source)).toString()); result.add(source.getOccupancy().toString());
result.add(plateVtoBMap.get(target).toString()); //beta sequence
result.add(target.getSequence().toString());
//beta well count //beta well count
result.add(betaWellCounts.get(plateVtoBMap.get(target)).toString()); result.add(target.getOccupancy().toString());
//overlap count //overlap count
result.add(Double.toString(graph.getEdgeWeight(e))); result.add(Double.toString(graph.getEdgeWeight(e)));
result.add(Boolean.toString(check)); result.add(Boolean.toString(check));
double pValue = Equations.pValue(numWells, alphaWellCounts.get(plateVtoAMap.get(source)), double pValue = Equations.pValue(numWells, source.getOccupancy(),
betaWellCounts.get(plateVtoBMap.get(target)), graph.getEdgeWeight(e)); target.getOccupancy(), graph.getEdgeWeight(e));
BigDecimal pValueTrunc = new BigDecimal(pValue, mc); BigDecimal pValueTrunc = new BigDecimal(pValue, mc);
result.add(pValueTrunc.toString()); result.add(pValueTrunc.toString());
allResults.add(result); allResults.add(result);

View File

@@ -1,23 +1,92 @@
import java.io.Serializable;
public class Vertex implements Serializable {
private SequenceType type;
private Integer vertexLabel;
private Integer sequence;
private Integer occupancy;
public class Vertex { public Vertex(Integer vertexLabel) {
private final Integer vertexLabel; this.vertexLabel = vertexLabel;
private final Integer sequence; }
private final Integer occupancy; public Vertex(String vertexLabel) {
this.vertexLabel = Integer.parseInt((vertexLabel));
}
public Vertex(Integer vertexLabel, Integer sequence, Integer occupancy) { public Vertex(SequenceType type, Integer sequence, Integer occupancy, Integer vertexLabel) {
this.type = type;
this.vertexLabel = vertexLabel; this.vertexLabel = vertexLabel;
this.sequence = sequence; this.sequence = sequence;
this.occupancy = occupancy; this.occupancy = occupancy;
} }
public Integer getVertexLabel() { return vertexLabel; }
public SequenceType getType() {
return type;
}
public void setType(String type) {
this.type = SequenceType.valueOf(type);
}
public Integer getVertexLabel() {
return vertexLabel;
}
public void setVertexLabel(String label) {
this.vertexLabel = Integer.parseInt(label);
}
public Integer getSequence() { public Integer getSequence() {
return sequence; return sequence;
} }
public void setSequence(String sequence) {
this.sequence = Integer.parseInt(sequence);
}
public Integer getOccupancy() { public Integer getOccupancy() {
return occupancy; return occupancy;
} }
public void setOccupancy(String occupancy) {
this.occupancy = Integer.parseInt(occupancy);
}
@Override //adapted from JGraphT example code
public int hashCode()
{
return (sequence == null) ? 0 : sequence.hashCode();
}
@Override //adapted from JGraphT example code
public boolean equals(Object obj)
{
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Vertex other = (Vertex) obj;
if (sequence == null) {
return other.sequence == null;
} else {
return sequence.equals(other.sequence);
}
}
@Override //adapted from JGraphT example code
public String toString()
{
StringBuilder sb = new StringBuilder();
sb.append("(").append(vertexLabel)
.append(", Type: ").append(type.name())
.append(", Sequence: ").append(sequence)
.append(", Occupancy: ").append(occupancy).append(")");
return sb.toString();
}
} }