diff --git a/src/main/java/GraphMLFileWriter.java b/src/main/java/GraphMLFileWriter.java index 96ad358..8411502 100644 --- a/src/main/java/GraphMLFileWriter.java +++ b/src/main/java/GraphMLFileWriter.java @@ -3,8 +3,9 @@ import org.jgrapht.graph.SimpleWeightedGraph; import org.jgrapht.nio.Attribute; import org.jgrapht.nio.AttributeType; import org.jgrapht.nio.DefaultAttribute; -import org.jgrapht.nio.dot.DOTExporter; 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.IOException; @@ -12,14 +13,14 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardOpenOption; import java.util.HashMap; -import java.util.LinkedHashMap; import java.util.Map; public class GraphMLFileWriter { String filename; + SimpleWeightedGraph graph; GraphWithMapData data; - + Map graphAttributes; public GraphMLFileWriter(String filename, GraphWithMapData data) { if(!filename.matches(".*\\.graphml")){ @@ -27,52 +28,61 @@ public class GraphMLFileWriter { } this.filename = filename; this.data = data; + this.graph = data.getGraph(); + graphAttributes = createGraphAttributes(); } -// public void writeGraphToFile() { -// try(BufferedWriter writer = Files.newBufferedWriter(Path.of(filename), StandardOpenOption.CREATE_NEW); -// ){ -// GraphMLExporter exporter = new GraphMLExporter<>(); -// exporter.exportGraph(graph, writer); -// } catch(IOException ex){ -// System.out.println("Could not make new file named "+filename); -// System.err.println(ex); -// } -// } + public GraphMLFileWriter(String filename, SimpleWeightedGraph graph) { + if(!filename.matches(".*\\.graphml")){ + filename = filename + ".graphml"; + } + this.filename = filename; + this.graph = graph; + } + + private Map createGraphAttributes(){ + Map 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() { - SimpleWeightedGraph graph = data.getGraph(); - Map vertexToAlphaMap = data.getPlateVtoAMap(); - Map vertexToBetaMap = data.getPlateVtoBMap(); - Map alphaOccs = data.getAlphaWellCounts(); - Map betaOccs = data.getBetaWellCounts(); try(BufferedWriter writer = Files.newBufferedWriter(Path.of(filename), StandardOpenOption.CREATE_NEW); ){ //create exporter. Let the vertex labels be the unique ids for the vertices - GraphMLExporter> exporter = new GraphMLExporter<>(v -> v.toString()); + GraphMLExporter> exporter = new GraphMLExporter<>(v -> v.getVertexLabel().toString()); //set to export weights exporter.setExportEdgeWeights(true); + //Set graph attributes + exporter.setGraphAttributeProvider( () -> graphAttributes); //set type, sequence, and occupancy attributes for each vertex exporter.setVertexAttributeProvider( v -> { Map attributes = new HashMap<>(); - if(vertexToAlphaMap.containsKey(v)) { - attributes.put("type", DefaultAttribute.createAttribute("CDR3 Alpha")); - attributes.put("sequence", DefaultAttribute.createAttribute(vertexToAlphaMap.get(v))); - 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)))); - } + attributes.put("type", DefaultAttribute.createAttribute(v.getType().name())); + attributes.put("sequence", DefaultAttribute.createAttribute(v.getSequence())); + attributes.put("occupancy", DefaultAttribute.createAttribute(v.getOccupancy())); return attributes; }); //register the attributes - exporter.registerAttribute("type", GraphMLExporter.AttributeCategory.NODE, AttributeType.STRING); - exporter.registerAttribute("sequence", GraphMLExporter.AttributeCategory.NODE, AttributeType.STRING); - exporter.registerAttribute("occupancy", GraphMLExporter.AttributeCategory.NODE, AttributeType.STRING); + for(String s : graphAttributes.keySet()) { + exporter.registerAttribute(s, AttributeCategory.GRAPH, 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 exporter.exportGraph(graph, writer); } catch(IOException ex){ @@ -81,4 +91,3 @@ public class GraphMLFileWriter { } } } - diff --git a/src/main/java/GraphModificationFunctions.java b/src/main/java/GraphModificationFunctions.java index a4ab1a0..68cc9d2 100644 --- a/src/main/java/GraphModificationFunctions.java +++ b/src/main/java/GraphModificationFunctions.java @@ -2,23 +2,25 @@ import org.jgrapht.graph.DefaultWeightedEdge; import org.jgrapht.graph.SimpleWeightedGraph; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Map; public interface GraphModificationFunctions { //remove over- and under-weight edges - static List filterByOverlapThresholds(SimpleWeightedGraph graph, + static Map filterByOverlapThresholds(SimpleWeightedGraph graph, int low, int high, boolean saveEdges) { - List removedEdges = new ArrayList<>(); + Map removedEdges = new HashMap<>(); + //List removedEdges = new ArrayList<>(); for (DefaultWeightedEdge e : graph.edgeSet()) { if ((graph.getEdgeWeight(e) > high) || (graph.getEdgeWeight(e) < low)) { if(saveEdges) { - Integer source = graph.getEdgeSource(e); - Integer target = graph.getEdgeTarget(e); + Vertex source = graph.getEdgeSource(e); + Vertex target = graph.getEdgeTarget(e); Integer weight = (int) graph.getEdgeWeight(e); - Integer[] edge = {source, target, weight}; - removedEdges.add(edge); + Vertex[] edge = {source, target}; + removedEdges.put(edge, weight); } else { graph.setEdgeWeight(e, 0.0); @@ -26,7 +28,7 @@ public interface GraphModificationFunctions { } } if(saveEdges) { - for (Integer[] edge : removedEdges) { + for (Vertex[] edge : removedEdges.keySet()) { graph.removeEdge(edge[0], edge[1]); } } @@ -34,23 +36,19 @@ public interface GraphModificationFunctions { } //Remove edges for pairs with large occupancy discrepancy - static List filterByRelativeOccupancy(SimpleWeightedGraph graph, - Map alphaWellCounts, - Map betaWellCounts, - Map plateVtoAMap, - Map plateVtoBMap, + static Map filterByRelativeOccupancy(SimpleWeightedGraph graph, Integer maxOccupancyDifference, boolean saveEdges) { - List removedEdges = new ArrayList<>(); + Map removedEdges = new HashMap<>(); for (DefaultWeightedEdge e : graph.edgeSet()) { - Integer alphaOcc = alphaWellCounts.get(plateVtoAMap.get(graph.getEdgeSource(e))); - Integer betaOcc = betaWellCounts.get(plateVtoBMap.get(graph.getEdgeTarget(e))); + Integer alphaOcc = graph.getEdgeSource(e).getOccupancy(); + Integer betaOcc = graph.getEdgeTarget(e).getOccupancy(); if (Math.abs(alphaOcc - betaOcc) >= maxOccupancyDifference) { if (saveEdges) { - Integer source = graph.getEdgeSource(e); - Integer target = graph.getEdgeTarget(e); + Vertex source = graph.getEdgeSource(e); + Vertex target = graph.getEdgeTarget(e); Integer weight = (int) graph.getEdgeWeight(e); - Integer[] edge = {source, target, weight}; - removedEdges.add(edge); + Vertex[] edge = {source, target}; + removedEdges.put(edge, weight); } else { graph.setEdgeWeight(e, 0.0); @@ -58,7 +56,7 @@ public interface GraphModificationFunctions { } } if(saveEdges) { - for (Integer[] edge : removedEdges) { + for (Vertex[] edge : removedEdges.keySet()) { 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 - static List filterByOverlapPercent(SimpleWeightedGraph graph, - Map alphaWellCounts, - Map betaWellCounts, - Map plateVtoAMap, - Map plateVtoBMap, + static Map filterByOverlapPercent(SimpleWeightedGraph graph, Integer minOverlapPercent, boolean saveEdges) { - List removedEdges = new ArrayList<>(); + Map removedEdges = new HashMap<>(); for (DefaultWeightedEdge e : graph.edgeSet()) { - Integer alphaOcc = alphaWellCounts.get(plateVtoAMap.get(graph.getEdgeSource(e))); - Integer betaOcc = betaWellCounts.get(plateVtoBMap.get(graph.getEdgeTarget(e))); + Integer alphaOcc = graph.getEdgeSource(e).getOccupancy(); + Integer betaOcc = graph.getEdgeTarget(e).getOccupancy(); double weight = graph.getEdgeWeight(e); double min = minOverlapPercent / 100.0; if ((weight / alphaOcc < min) || (weight / betaOcc < min)) { - if(saveEdges) { - Integer source = graph.getEdgeSource(e); - Integer target = graph.getEdgeTarget(e); + if (saveEdges) { + Vertex source = graph.getEdgeSource(e); + Vertex target = graph.getEdgeTarget(e); Integer intWeight = (int) graph.getEdgeWeight(e); - Integer[] edge = {source, target, intWeight}; - removedEdges.add(edge); + Vertex[] edge = {source, target}; + removedEdges.put(edge, intWeight); } else { graph.setEdgeWeight(e, 0.0); @@ -93,18 +87,18 @@ public interface GraphModificationFunctions { } } if(saveEdges) { - for (Integer[] edge : removedEdges) { + for (Vertex[] edge : removedEdges.keySet()) { graph.removeEdge(edge[0], edge[1]); } } return removedEdges; } - static void addRemovedEdges(SimpleWeightedGraph graph, - List removedEdges) { - for (Integer[] edge : removedEdges) { + static void addRemovedEdges(SimpleWeightedGraph graph, + Map removedEdges) { + for (Vertex[] edge : removedEdges.keySet()) { DefaultWeightedEdge e = graph.addEdge(edge[0], edge[1]); - graph.setEdgeWeight(e, (double) edge[2]); + graph.setEdgeWeight(e, removedEdges.get(edge)); } } diff --git a/src/main/java/GraphWithMapData.java b/src/main/java/GraphWithMapData.java index 3795190..0e4c09b 100644 --- a/src/main/java/GraphWithMapData.java +++ b/src/main/java/GraphWithMapData.java @@ -15,32 +15,33 @@ public class GraphWithMapData implements java.io.Serializable { private Integer alphaCount; private Integer betaCount; private final Map distCellsMapAlphaKey; - private final Map plateVtoAMap; - private final Map plateVtoBMap; - private final Map plateAtoVMap; - private final Map plateBtoVMap; - private final Map alphaWellCounts; - private final Map betaWellCounts; +// private final Map plateVtoAMap; +// private final Map plateVtoBMap; +// private final Map plateAtoVMap; +// private final Map plateBtoVMap; +// private final Map alphaWellCounts; +// private final Map betaWellCounts; private final Duration time; public GraphWithMapData(SimpleWeightedGraph graph, Integer numWells, Integer[] wellConcentrations, - Integer alphaCount, Integer betaCount, - Map distCellsMapAlphaKey, Map plateVtoAMap, - Map plateVtoBMap, Map plateAtoVMap, - Map plateBtoVMap, Map alphaWellCounts, - Map betaWellCounts, Duration time) { + Map distCellsMapAlphaKey, Duration time){ + +// Map plateVtoAMap, Integer alphaCount, Integer betaCount, +// Map plateVtoBMap, Map plateAtoVMap, +// Map plateBtoVMap, Map alphaWellCounts, +// Map betaWellCounts,) { this.graph = graph; this.numWells = numWells; this.wellPopulations = wellConcentrations; this.alphaCount = alphaCount; this.betaCount = betaCount; this.distCellsMapAlphaKey = distCellsMapAlphaKey; - this.plateVtoAMap = plateVtoAMap; - this.plateVtoBMap = plateVtoBMap; - this.plateAtoVMap = plateAtoVMap; - this.plateBtoVMap = plateBtoVMap; - this.alphaWellCounts = alphaWellCounts; - this.betaWellCounts = betaWellCounts; +// this.plateVtoAMap = plateVtoAMap; +// this.plateVtoBMap = plateVtoBMap; +// this.plateAtoVMap = plateAtoVMap; +// this.plateBtoVMap = plateBtoVMap; +// this.alphaWellCounts = alphaWellCounts; +// this.betaWellCounts = betaWellCounts; this.time = time; } @@ -56,41 +57,41 @@ public class GraphWithMapData implements java.io.Serializable { return wellPopulations; } - public Integer getAlphaCount() { - return alphaCount; - } - - public Integer getBetaCount() { - return betaCount; - } +// public Integer getAlphaCount() { +// return alphaCount; +// } +// +// public Integer getBetaCount() { +// return betaCount; +// } public Map getDistCellsMapAlphaKey() { return distCellsMapAlphaKey; } - public Map getPlateVtoAMap() { - return plateVtoAMap; - } - - public Map getPlateVtoBMap() { - return plateVtoBMap; - } - - public Map getPlateAtoVMap() { - return plateAtoVMap; - } - - public Map getPlateBtoVMap() { - return plateBtoVMap; - } - - public Map getAlphaWellCounts() { - return alphaWellCounts; - } - - public Map getBetaWellCounts() { - return betaWellCounts; - } +// public Map getPlateVtoAMap() { +// return plateVtoAMap; +// } +// +// public Map getPlateVtoBMap() { +// return plateVtoBMap; +// } +// +// public Map getPlateAtoVMap() { +// return plateAtoVMap; +// } +// +// public Map getPlateBtoVMap() { +// return plateBtoVMap; +// } +// +// public Map getAlphaWellCounts() { +// return alphaWellCounts; +// } +// +// public Map getBetaWellCounts() { +// return betaWellCounts; +// } public Duration getTime() { return time; diff --git a/src/main/java/SequenceType.java b/src/main/java/SequenceType.java new file mode 100644 index 0000000..54de083 --- /dev/null +++ b/src/main/java/SequenceType.java @@ -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 +} diff --git a/src/main/java/Simulator.java b/src/main/java/Simulator.java index 933ad0e..c94db0c 100644 --- a/src/main/java/Simulator.java +++ b/src/main/java/Simulator.java @@ -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 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) { Instant start = Instant.now(); List distinctCells = cellSample.getCells(); - int[] alphaIndex = {cdr3AlphaIndex}; - int[] betaIndex = {cdr3BetaIndex}; + int[] alphaIndices = {SequenceType.CDR3_ALPHA.ordinal()}; + int[] betaIndices = {SequenceType.CDR3_BETA.ordinal()}; int numWells = samplePlate.getSize(); if(verbose){System.out.println("Making cell maps");} //HashMap keyed to Alphas, values Betas - Map distCellsMapAlphaKey = makeSequenceToSequenceMap(distinctCells, cdr3AlphaIndex, cdr3BetaIndex); + Map distCellsMapAlphaKey = makeSequenceToSequenceMap(distinctCells, 0, 1); if(verbose){System.out.println("Cell maps made");} if(verbose){System.out.println("Making well maps");} - Map allAlphas = samplePlate.assayWellsSequenceS(alphaIndex); - Map allBetas = samplePlate.assayWellsSequenceS(betaIndex); + + Map allAlphas = samplePlate.assayWellsSequenceS(alphaIndices); + Map allBetas = samplePlate.assayWellsSequenceS(betaIndices); int alphaCount = allAlphas.size(); if(verbose){System.out.println("All alphas count: " + alphaCount);} 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 //for a bipartite graph, and all the SimpleWeightedBipartiteGraphMatrixGenerator class expects.) 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 alphaWellCounts = new HashMap<>(); - //count how many wells each beta appears in + //count how many wells each beta sequence appears in Map betaWellCounts = new HashMap<>(); //the adjacency matrix to be used by the graph generator double[][] weights = new double[plateVtoAMap.size()][plateVtoBMap.size()]; countSequencesAndFillMatrix(samplePlate, allAlphas, allBetas, plateAtoVMap, - plateBtoVMap, alphaIndex, betaIndex, alphaWellCounts, betaWellCounts, weights); + plateBtoVMap, alphaIndices, betaIndices, alphaWellCounts, betaWellCounts, weights); if(verbose){System.out.println("Matrix created");} //create bipartite graph if(verbose){System.out.println("Creating graph");} //the graph object - SimpleWeightedGraph graph = + SimpleWeightedGraph graph = new SimpleWeightedGraph<>(DefaultWeightedEdge.class); //the graph generator SimpleWeightedBipartiteGraphMatrixGenerator graphGenerator = new SimpleWeightedBipartiteGraphMatrixGenerator(); //the list of alpha vertices - List alphaVertices = new ArrayList<>(plateVtoAMap.keySet()); //This will work because LinkedHashMap preserves order of entry + //List alphaVertices = new ArrayList<>(plateVtoAMap.keySet()); //This will work because LinkedHashMap preserves order of entry + List 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); //the list of beta vertices - List betaVertices = new ArrayList<>(plateVtoBMap.keySet()); - graphGenerator.second(betaVertices); //This will work because LinkedHashMap preserves order of entry + //List betaVertices = new ArrayList<>(plateVtoBMap.keySet());//This will work because LinkedHashMap preserves order of entry + List 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 graphGenerator.weights(weights); graphGenerator.generateGraph(graph); @@ -112,9 +123,7 @@ public class Simulator implements GraphModificationFunctions { Duration time = Duration.between(start, stop); //create GraphWithMapData object - GraphWithMapData output = new GraphWithMapData(graph, numWells, samplePlate.getPopulations(), alphaCount, betaCount, - distCellsMapAlphaKey, plateVtoAMap, plateVtoBMap, plateAtoVMap, - plateBtoVMap, alphaWellCounts, betaWellCounts, time); + GraphWithMapData output = new GraphWithMapData(graph, numWells, samplePlate.getPopulations(), distCellsMapAlphaKey, time); //Set source file name in graph to name of sample plate output.setSourceFilename(samplePlate.getFilename()); //return GraphWithMapData object @@ -126,39 +135,46 @@ public class Simulator implements GraphModificationFunctions { Integer highThreshold, Integer maxOccupancyDifference, Integer minOverlapPercent, boolean verbose) { Instant start = Instant.now(); - List removedEdges = new ArrayList<>(); + SimpleWeightedGraph graph = data.getGraph(); + Map removedEdges = new HashMap<>(); boolean saveEdges = BiGpairSEQ.cacheGraph(); int numWells = data.getNumWells(); - Integer alphaCount = data.getAlphaCount(); - Integer betaCount = data.getBetaCount(); + //Integer alphaCount = data.getAlphaCount(); + //Integer betaCount = data.getBetaCount(); Map distCellsMapAlphaKey = data.getDistCellsMapAlphaKey(); - Map plateVtoAMap = data.getPlateVtoAMap(); - Map plateVtoBMap = data.getPlateVtoBMap(); - Map alphaWellCounts = data.getAlphaWellCounts(); - Map betaWellCounts = data.getBetaWellCounts(); - SimpleWeightedGraph graph = data.getGraph(); + Set alphas = new HashSet<>(); + Set betas = new HashSet<>(); + for(Vertex v: graph.vertexSet()) { + if (SequenceType.CDR3_ALPHA.equals(v.getType())){ + 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 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");} //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() + " percent of vertex occupancy value.");} - removedEdges.addAll(GraphModificationFunctions.filterByOverlapPercent(graph, alphaWellCounts, betaWellCounts, - plateVtoAMap, plateVtoBMap, minOverlapPercent, saveEdges)); + removedEdges.putAll(GraphModificationFunctions.filterByOverlapPercent(graph, minOverlapPercent, saveEdges)); if(verbose){System.out.println("Edges with weights too far below a vertex occupancy value removed");} //Filter by relative occupancy if(verbose){System.out.println("Eliminating edges between vertices with occupancy difference > " + maxOccupancyDifference);} - removedEdges.addAll(GraphModificationFunctions.filterByRelativeOccupancy(graph, alphaWellCounts, betaWellCounts, - plateVtoAMap, plateVtoBMap, maxOccupancyDifference, saveEdges)); + removedEdges.putAll(GraphModificationFunctions.filterByRelativeOccupancy(graph, maxOccupancyDifference, saveEdges)); if(verbose){System.out.println("Edges between vertices of with excessively different occupancy values " + "removed");} //Find Maximum Weighted Matching + //using jheaps library class PairingHeap for improved efficiency if(verbose){System.out.println("Finding maximum weighted matching");} MaximumWeightBipartiteMatching maxWeightMatching; //Use correct heap type for priority queue @@ -166,20 +182,20 @@ public class Simulator implements GraphModificationFunctions { switch (heapType) { case "PAIRING" -> { maxWeightMatching = new MaximumWeightBipartiteMatching(graph, - plateVtoAMap.keySet(), - plateVtoBMap.keySet(), + alphas, + betas, i -> new PairingHeap(Comparator.naturalOrder())); } case "FIBONACCI" -> { maxWeightMatching = new MaximumWeightBipartiteMatching(graph, - plateVtoAMap.keySet(), - plateVtoBMap.keySet(), + alphas, + betas, i -> new FibonacciHeap(Comparator.naturalOrder())); } default -> { maxWeightMatching = new MaximumWeightBipartiteMatching(graph, - plateVtoAMap.keySet(), - plateVtoBMap.keySet()); + alphas, + betas); } } //get the matching @@ -209,11 +225,14 @@ public class Simulator implements GraphModificationFunctions { Map matchMap = new HashMap<>(); while(weightIter.hasNext()) { e = weightIter.next(); - Integer source = graph.getEdgeSource(e); - Integer target = graph.getEdgeTarget(e); + Vertex source = graph.getEdgeSource(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! - matchMap.put(plateVtoAMap.get(source), plateVtoBMap.get(target)); - check = plateVtoBMap.get(target).equals(distCellsMapAlphaKey.get(plateVtoAMap.get(source))); + matchMap.put(source.getSequence(), target.getSequence()); + check = target.getSequence().equals(distCellsMapAlphaKey.get(source.getSequence())); + //check = plateVtoBMap.get(target).equals(distCellsMapAlphaKey.get(plateVtoAMap.get(source))); if(check) { trueCount++; } @@ -221,17 +240,19 @@ public class Simulator implements GraphModificationFunctions { falseCount++; } List result = new ArrayList<>(); - result.add(plateVtoAMap.get(source).toString()); + //alpha sequence + result.add(source.getSequence().toString()); //alpha well count - result.add(alphaWellCounts.get(plateVtoAMap.get(source)).toString()); - result.add(plateVtoBMap.get(target).toString()); + result.add(source.getOccupancy().toString()); + //beta sequence + result.add(target.getSequence().toString()); //beta well count - result.add(betaWellCounts.get(plateVtoBMap.get(target)).toString()); + result.add(target.getOccupancy().toString()); //overlap count result.add(Double.toString(graph.getEdgeWeight(e))); result.add(Boolean.toString(check)); - double pValue = Equations.pValue(numWells, alphaWellCounts.get(plateVtoAMap.get(source)), - betaWellCounts.get(plateVtoBMap.get(target)), graph.getEdgeWeight(e)); + double pValue = Equations.pValue(numWells, source.getOccupancy(), + target.getOccupancy(), graph.getEdgeWeight(e)); BigDecimal pValueTrunc = new BigDecimal(pValue, mc); result.add(pValueTrunc.toString()); allResults.add(result); diff --git a/src/main/java/Vertex.java b/src/main/java/Vertex.java index ef962ae..a7ddda9 100644 --- a/src/main/java/Vertex.java +++ b/src/main/java/Vertex.java @@ -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 { - private final Integer vertexLabel; - private final Integer sequence; - private final Integer occupancy; + public Vertex(Integer vertexLabel) { + this.vertexLabel = vertexLabel; + } + 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.sequence = sequence; 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() { + return sequence; } + public void setSequence(String sequence) { + this.sequence = Integer.parseInt(sequence); + } + public Integer getOccupancy() { 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(); + } + }