Re-implement command line options

This commit is contained in:
2022-02-27 15:35:07 -06:00
parent a5f7c0641d
commit 5246cc4a0c
3 changed files with 307 additions and 227 deletions

View File

@@ -23,8 +23,8 @@ public class BiGpairSEQ {
} }
else { else {
//This will be uncommented when command line arguments are re-implemented. //This will be uncommented when command line arguments are re-implemented.
//CommandLineInterface.startCLI(args); CommandLineInterface.startCLI(args);
System.out.println("Command line arguments are still being re-implemented."); //System.out.println("Command line arguments are still being re-implemented.");
} }
} }

View File

@@ -1,5 +1,8 @@
import org.apache.commons.cli.*; import org.apache.commons.cli.*;
import java.io.IOException;
import java.util.stream.Stream;
/* /*
* Class for parsing options passed to program from command line * Class for parsing options passed to program from command line
* *
@@ -29,6 +32,8 @@ import org.apache.commons.cli.*;
* cellfile : name of the cell sample file to use as input * cellfile : name of the cell sample file to use as input
* platefile : name of the sample plate file to use as input * platefile : name of the sample plate file to use as input
* output : name of the output file * output : name of the output file
* graphml : output a graphml file
* binary : output a serialized binary object file
* *
* Match flags: * Match flags:
* graphFile : name of graph and data file to use as input * graphFile : name of graph and data file to use as input
@@ -49,23 +54,156 @@ public class CommandLineInterface {
//should be three separate programs. //should be three separate programs.
//There might be a way to do it with option parameters? //There might be a way to do it with option parameters?
//main options set //main options set - for the four different program modes
Options mainOptions = buildMainOptions();
CommandLineParser parser = new DefaultParser();
try{
CommandLine line = parser.parse(mainOptions, args);
if (line.hasOption("cells")) {
Options cellOptions = buildCellOptions();
line = parser.parse(cellOptions, args);
Integer number = Integer.valueOf(line.getOptionValue("n"));
Integer diversity = Integer.valueOf(line.getOptionValue("d"));
String filename = line.getOptionValue("o");
makeCells(filename, number, diversity);
}
else if (line.hasOption("plate")) {
Options plateOptions = buildPlateOptions();
line = parser.parse(plateOptions, args);
//get the cells
String cellFilename = line.getOptionValue("c");
CellSample cells = getCells(cellFilename);
//get the rest of the parameters
Integer[] populations;
String outputFilename = line.getOptionValue("o");
Integer numWells = Integer.parseInt(line.getOptionValue("w"));
Double dropoutRate = Double.parseDouble(line.getOptionValue("err"));
if (line.hasOption("random")) {
//Array holding values of minimum and maximum populations
Integer[] min_max = Stream.of(line.getOptionValues("random"))
.mapToInt(Integer::parseInt)
.boxed()
.toArray(Integer[]::new);
populations = BiGpairSEQ.getRand().ints(min_max[0], min_max[1] + 1)
.limit(numWells)
.boxed()
.toArray(Integer[]::new);
}
else if (line.hasOption("pop")) {
populations = Stream.of(line.getOptionValues("pop"))
.mapToInt(Integer::parseInt)
.boxed()
.toArray(Integer[]::new);
}
else{
populations = new Integer[1];
populations[0] = 1;
}
//make the plate
Plate plate;
if (line.hasOption("poisson")) {
Double stdDev = Math.sqrt(numWells);
plate = new Plate(cells, cellFilename, numWells, populations, dropoutRate, stdDev, false);
}
else if (line.hasOption("gaussian")) {
Double stdDev = Double.parseDouble(line.getOptionValue("stddev"));
plate = new Plate(cells, cellFilename, numWells, populations, dropoutRate, stdDev, false);
}
else {
assert line.hasOption("exponential");
Double lambda = Double.parseDouble(line.getOptionValue("lambda"));
plate = new Plate(cells, cellFilename, numWells, populations, dropoutRate, lambda, true);
}
PlateFileWriter writer = new PlateFileWriter(outputFilename, plate);
writer.writePlateFile();
}
else if (line.hasOption("graph")) { //Making a graph
Options graphOptions = buildGraphOptions();
line = parser.parse(graphOptions, args);
String cellFilename = line.getOptionValue("c");
String plateFilename = line.getOptionValue("p");
String outputFilename = line.getOptionValue("o");
//get cells
CellSample cells = getCells(cellFilename);
//get plate
Plate plate = getPlate(plateFilename);
GraphWithMapData graph = Simulator.makeGraph(cells, plate, false);
if (!line.hasOption("no-binary")) { //output binary file unless told not to
GraphDataObjectWriter writer = new GraphDataObjectWriter(outputFilename, graph);
writer.writeDataToFile();
}
if (line.hasOption("graphml")) { //if told to, output graphml file
GraphMLFileWriter gmlwriter = new GraphMLFileWriter(outputFilename, graph);
gmlwriter.writeGraphToFile();
}
}
else if (line.hasOption("match")) { //can add a flag for which match type in future, spit this in two
Options matchOptions = buildMatchCDR3options();
line = parser.parse(matchOptions, args);
String graphFilename = line.getOptionValue("g");
String outputFilename = line.getOptionValue("o");
Integer minThreshold = Integer.parseInt(line.getOptionValue("min"));
Integer maxThreshold = Integer.parseInt(line.getOptionValue("max"));
Integer minOverlapPct;
if (line.hasOption("minpct")) { //see if this filter is being used
minOverlapPct = Integer.parseInt(line.getOptionValue("minpct"));
}
else {
minOverlapPct = 0;
}
Integer maxOccupancyDiff;
if (line.hasOption("maxdiff")) { //see if this filter is being used
maxOccupancyDiff = Integer.parseInt(line.getOptionValue("maxdiff"));
}
else {
maxOccupancyDiff = Integer.MAX_VALUE;
}
GraphWithMapData graph = getGraph(graphFilename);
MatchingResult result = Simulator.matchCDR3s(graph, graphFilename, minThreshold, maxThreshold,
maxOccupancyDiff, minOverlapPct, false);
MatchingFileWriter writer = new MatchingFileWriter(outputFilename, result);
writer.writeResultsToFile();
//can put a bunch of ifs for outputting various things from the MatchingResult to System.out here
//after I put those flags in the matchOptions
}
}
catch (ParseException exp) {
System.err.println("Parsing failed. Reason: " + exp.getMessage());
}
}
private static Option outputFileOption() {
Option outputFile = Option.builder("o")
.longOpt("output-file")
.hasArg()
.argName("filename")
.desc("Name of output file")
.required()
.build();
return outputFile;
}
private static Options buildMainOptions() {
Options mainOptions = new Options(); Options mainOptions = new Options();
Option makeCells = Option.builder("cells") Option makeCells = Option.builder("cells")
.longOpt("make-cells") .longOpt("make-cells")
.desc("Makes a file of distinct cells") .desc("Makes a cell sample file of distinct T cells")
.build(); .build();
Option makePlate = Option.builder("plates") Option makePlate = Option.builder("plates")
.longOpt("make-plates") .longOpt("make-plates")
.desc("Makes a sample plate file") .desc("Makes a sample plate file. Requires a cell sample file.")
.build(); .build();
Option makeGraph = Option.builder("graph") Option makeGraph = Option.builder("graph")
.longOpt("make-graph") .longOpt("make-graph")
.desc("Makes a graph and data file") .desc("Makes a graph/data file. Requires a cell sample file and a sample plate file")
.build(); .build();
Option matchCDR3 = Option.builder("match") Option matchCDR3 = Option.builder("match")
.longOpt("match-cdr3") .longOpt("match-cdr3")
.desc("Match CDR3s. Requires a cell sample file and any number of plate files.") .desc("Matches CDR3s. Requires a graph/data file.")
.build(); .build();
OptionGroup mainGroup = new OptionGroup(); OptionGroup mainGroup = new OptionGroup();
mainGroup.addOption(makeCells); mainGroup.addOption(makeCells);
@@ -74,255 +212,197 @@ public class CommandLineInterface {
mainGroup.addOption(matchCDR3); mainGroup.addOption(matchCDR3);
mainGroup.setRequired(true); mainGroup.setRequired(true);
mainOptions.addOptionGroup(mainGroup); mainOptions.addOptionGroup(mainGroup);
return mainOptions;
}
//Reuse clones of this for other options groups, rather than making it lots of times private static Options buildCellOptions() {
Option outputFile = Option.builder("o") Options cellOptions = new Options();
.longOpt("output-file") Option numCells = Option.builder("n")
.hasArg()
.argName("filename")
.desc("Name of output file")
.build();
mainOptions.addOption(outputFile);
//Options cellOptions = new Options();
Option numCells = Option.builder("nc")
.longOpt("num-cells") .longOpt("num-cells")
.desc("The number of distinct cells to generate") .desc("The number of distinct cells to generate")
.hasArg() .hasArg()
.argName("number") .argName("number")
.build(); .required().build();
mainOptions.addOption(numCells); Option cdr3Diversity = Option.builder("d")
Option cdr1Freq = Option.builder("d") .longOpt("diversity-factor")
.longOpt("peptide-diversity-factor") .desc("The factor by which unique CDR3s outnumber unique CDR1s")
.hasArg() .hasArg()
.argName("number") .argName("factor")
.desc("Number of distinct CDR3s for every CDR1") .required().build();
.build(); cellOptions.addOption(numCells);
mainOptions.addOption(cdr1Freq); cellOptions.addOption(cdr3Diversity);
//Option cellOutput = (Option) outputFile.clone(); cellOptions.addOption(outputFileOption());
//cellOutput.setRequired(true); return cellOptions;
//mainOptions.addOption(cellOutput); }
//Options plateOptions = new Options(); private static Options buildPlateOptions() {
Option inputCells = Option.builder("c") Options plateOptions = new Options();
Option cellFile = Option.builder("c") // add this to plate options
.longOpt("cell-file") .longOpt("cell-file")
.desc("The cell sample file to use")
.hasArg() .hasArg()
.argName("file") .required().build();
.desc("The cell sample file used for filling wells") Option numWells = Option.builder("w")// add this to plate options
.build(); .longOpt("wells")
mainOptions.addOption(inputCells); .desc("The number of wells on the sample plate")
Option numWells = Option.builder("w")
.longOpt("num-wells")
.hasArg() .hasArg()
.argName("number") .required().build();
.desc("The number of wells on each plate") //options group for choosing with distribution to use
OptionGroup distributions = new OptionGroup();// add this to plate options
distributions.setRequired(true);
Option poisson = Option.builder("poisson")
.desc("Use a Poisson distribution for cell sample")
.build(); .build();
mainOptions.addOption(numWells); Option gaussian = Option.builder("gaussian")
Option numPlates = Option.builder("np") .desc("Use a Gaussian distribution for cell sample")
.longOpt("num-plates") .build();
Option exponential = Option.builder("exponential")
.desc("Use an exponential distribution for cell sample")
.build();
distributions.addOption(poisson);
distributions.addOption(gaussian);
distributions.addOption(exponential);
//options group for statistical distribution parameters
OptionGroup statParams = new OptionGroup();// add this to plate options
Option stdDev = Option.builder("stddev")
.desc("Standard deviation for Gaussian distribution")
.hasArg() .hasArg()
.argName("number")
.desc("The number of plate files to output")
.build(); .build();
mainOptions.addOption(numPlates); Option lambda = Option.builder("lambda")
//Option plateOutput = (Option) outputFile.clone(); .desc("Lambda value for exponential distribution")
//plateOutput.setRequired(true);
//plateOutput.setDescription("Prefix for plate output filenames");
//mainOptions.addOption(plateOutput);
Option plateErr = Option.builder("err")
.longOpt("drop-out-rate")
.hasArg() .hasArg()
.argName("number")
.desc("Well drop-out rate. (Probability between 0 and 1)")
.build(); .build();
mainOptions.addOption(plateErr); statParams.addOption(stdDev);
Option plateConcentrations = Option.builder("t") statParams.addOption(lambda);
.longOpt("t-cells-per-well") //Option group for random plate or set populations
OptionGroup wellPopOptions = new OptionGroup(); // add this to plate options
wellPopOptions.setRequired(true);
Option randomWellPopulations = Option.builder("random")
.desc("Randomize well populations on sample plate.")
.hasArgs() .hasArgs()
.argName("number 1, number 2, ...") .argName("MIN_POP MAX_POP")
.desc("Number of T cells per well for each plate section")
.build(); .build();
mainOptions.addOption(plateConcentrations); Option specificWellPopulations = Option.builder("pop")
.longOpt("populations")
//different distributions, mutually exclusive .desc("The well populations for each section of the sample plate")
OptionGroup plateDistributions = new OptionGroup();
Option plateExp = Option.builder("exponential")
.desc("Sample from distinct cells with exponential frequency distribution")
.build();
plateDistributions.addOption(plateExp);
Option plateGaussian = Option.builder("gaussian")
.desc("Sample from distinct cells with gaussain frequency distribution")
.build();
plateDistributions.addOption(plateGaussian);
Option platePoisson = Option.builder("poisson")
.desc("Sample from distinct cells with poisson frequency distribution")
.build();
plateDistributions.addOption(platePoisson);
mainOptions.addOptionGroup(plateDistributions);
Option plateStdDev = Option.builder("stddev")
.desc("Standard deviation for gaussian distribution")
.hasArg()
.argName("number")
.build();
mainOptions.addOption(plateStdDev);
Option plateLambda = Option.builder("lambda")
.desc("Lambda for exponential distribution")
.hasArg()
.argName("number")
.build();
mainOptions.addOption(plateLambda);
//
// String cellFile, String filename, Double stdDev,
// Integer numWells, Integer numSections,
// Integer[] concentrations, Double dropOutRate
//
//Options matchOptions = new Options();
inputCells.setDescription("The cell sample file to be used for matching.");
mainOptions.addOption(inputCells);
Option lowThresh = Option.builder("low")
.longOpt("low-threshold")
.hasArg()
.argName("number")
.desc("Sets the minimum occupancy overlap to attempt matching")
.build();
mainOptions.addOption(lowThresh);
Option highThresh = Option.builder("high")
.longOpt("high-threshold")
.hasArg()
.argName("number")
.desc("Sets the maximum occupancy overlap to attempt matching")
.build();
mainOptions.addOption(highThresh);
Option occDiff = Option.builder("occdiff")
.longOpt("occupancy-difference")
.hasArg()
.argName("Number")
.desc("Maximum difference in alpha/beta occupancy to attempt matching")
.build();
mainOptions.addOption(occDiff);
Option overlapPer = Option.builder("ovper")
.longOpt("overlap-percent")
.hasArg()
.argName("Percent")
.desc("Minimum overlap percent to attempt matching (0 -100)")
.build();
mainOptions.addOption(overlapPer);
Option inputPlates = Option.builder("p")
.longOpt("plate-files")
.hasArgs() .hasArgs()
.desc("Plate files to match") .argName("SECTION_1_POP [SECTION_2_POP] [SECTION_3_POP] ...")
.build(); .build();
mainOptions.addOption(inputPlates); Option dropoutRate = Option.builder("err") //add this to plate options
.longOpt("dropout-rate")
.hasArg()
.desc("The sequence dropout rate due to amplification error")
.argName("DROPOUT_RATE (value between 0.0 and 1.0)")
.required()
.build();
wellPopOptions.addOption(randomWellPopulations);
wellPopOptions.addOption(specificWellPopulations);
plateOptions.addOption(cellFile);
plateOptions.addOption(numWells);
plateOptions.addOptionGroup(distributions);
plateOptions.addOptionGroup(statParams);
plateOptions.addOptionGroup(wellPopOptions);
plateOptions.addOption(dropoutRate);
plateOptions.addOption(outputFileOption());
return plateOptions;
}
private static Options buildGraphOptions() {
Options graphOptions = new Options();
Option cellFilename = Option.builder("c")
.longOpt("cell-file")
.desc("Cell sample file to use for checking accuracy")
.hasArg()
.argName("CELL_FILENAME")
.required().build();
Option plateFilename = Option.builder("p")
.longOpt("plate-filename")
.desc("Sample plate file (made from given cell sample file) to construct graph from")
.hasArg()
.argName("PLATE_FILENAME")
.required().build();
Option outputGraphML = Option.builder("graphml")
.desc("Output GraphML file")
.build();
Option outputSerializedBinary = Option.builder("no-binary")
.desc("Don't output serialized binary file")
.build();
graphOptions.addOption(cellFilename);
graphOptions.addOption(plateFilename);
graphOptions.addOption(outputFileOption());
return graphOptions;
}
private static Options buildMatchCDR3options() {
Options matchCDR3options = new Options();
Option graphFilename = Option.builder("g")
.longOpt("graph-file")
.desc("Graph/data file to use")
.hasArg()
.argName("GRAPH/DATA_FILENAME")
.required().build();
Option minOccupancyOverlap = Option.builder("min")
.longOpt("min-overlap-size")
.desc("The minimum number of shared wells to attempt to match a sequence pair")
.hasArg()
.argName("MIN_OVERLAP")
.required().build();
Option maxOccupancyOverlap = Option.builder("max")
.longOpt("max_overlap_size")
.desc("The maximum number of shared wells to attempt to match a sequence pair")
.hasArg()
.argName("MAX_OVERLAP")
.required().build();
Option minOverlapPercent = Option.builder("minpct")
.longOpt("min-overlap-percent")
.desc("The minimum percentage of a sequence's total occupancy shared by another sequence to attempt matching")
.hasArg()
.build();
Option maxOccupancyDifference = Option.builder("maxdiff")
.longOpt("max-occupancy-difference")
.desc("The maximum difference in total occupancy between two sequences to attempt matching")
.hasArg()
.build();
matchCDR3options.addOption(graphFilename);
matchCDR3options.addOption(minOccupancyOverlap);
matchCDR3options.addOption(maxOccupancyOverlap);
matchCDR3options.addOption(minOverlapPercent);
matchCDR3options.addOption(maxOccupancyDifference);
matchCDR3options.addOption(outputFileOption());
return matchCDR3options;
}
CommandLineParser parser = new DefaultParser(); private static CellSample getCells(String cellFilename) {
try { assert cellFilename != null;
CommandLine line = parser.parse(mainOptions, args); CellFileReader reader = new CellFileReader(cellFilename);
if(line.hasOption("match")){ return reader.getCellSample();
//line = parser.parse(mainOptions, args); }
//String cellFile = line.getOptionValue("c");
String graphFile = line.getOptionValue("g");
Integer lowThreshold = Integer.valueOf(line.getOptionValue(lowThresh));
Integer highThreshold = Integer.valueOf(line.getOptionValue(highThresh));
Integer occupancyDifference = Integer.valueOf(line.getOptionValue(occDiff));
Integer overlapPercent = Integer.valueOf(line.getOptionValue(overlapPer));
for(String plate: line.getOptionValues("p")) {
matchCDR3s(graphFile, lowThreshold, highThreshold, occupancyDifference, overlapPercent);
}
}
else if(line.hasOption("cells")){
//line = parser.parse(mainOptions, args);
String filename = line.getOptionValue("o");
Integer numDistCells = Integer.valueOf(line.getOptionValue("nc"));
Integer freq = Integer.valueOf(line.getOptionValue("d"));
makeCells(filename, numDistCells, freq);
}
else if(line.hasOption("plates")){
//line = parser.parse(mainOptions, args);
String cellFile = line.getOptionValue("c");
String filenamePrefix = line.getOptionValue("o");
Integer numWellsOnPlate = Integer.valueOf(line.getOptionValue("w"));
Integer numPlatesToMake = Integer.valueOf(line.getOptionValue("np"));
String[] concentrationsToUseString = line.getOptionValues("t");
Integer numSections = concentrationsToUseString.length;
Integer[] concentrationsToUse = new Integer[numSections]; private static Plate getPlate(String plateFilename) {
for(int i = 0; i <numSections; i++){ assert plateFilename != null;
concentrationsToUse[i] = Integer.valueOf(concentrationsToUseString[i]); PlateFileReader reader = new PlateFileReader(plateFilename);
} return reader.getSamplePlate();
Double dropOutRate = Double.valueOf(line.getOptionValue("err")); }
if(line.hasOption("exponential")){
Double lambda = Double.valueOf(line.getOptionValue("lambda")); private static GraphWithMapData getGraph(String graphFilename) {
for(int i = 1; i <= numPlatesToMake; i++){ assert graphFilename != null;
makePlateExp(cellFile, filenamePrefix + i, lambda, numWellsOnPlate, try{
concentrationsToUse,dropOutRate); GraphDataObjectReader reader = new GraphDataObjectReader(graphFilename);
} return reader.getData();
}
else if(line.hasOption("gaussian")){
Double stdDev = Double.valueOf(line.getOptionValue("std-dev"));
for(int i = 1; i <= numPlatesToMake; i++){
makePlate(cellFile, filenamePrefix + i, stdDev, numWellsOnPlate,
concentrationsToUse,dropOutRate);
}
}
else if(line.hasOption("poisson")){
for(int i = 1; i <= numPlatesToMake; i++){
makePlatePoisson(cellFile, filenamePrefix + i, numWellsOnPlate,
concentrationsToUse,dropOutRate);
}
}
}
} }
catch (ParseException exp) { catch (IOException ex) {
System.err.println("Parsing failed. Reason: " + exp.getMessage()); ex.printStackTrace();
return null;
} }
} }
//for calling from command line //for calling from command line
public static void makeCells(String filename, Integer numCells, Integer cdr1Freq){ public static void makeCells(String filename, Integer numCells, Integer cdr1Freq) {
CellSample sample = new CellSample(numCells, cdr1Freq); CellSample sample = new CellSample(numCells, cdr1Freq);
CellFileWriter writer = new CellFileWriter(filename, sample); CellFileWriter writer = new CellFileWriter(filename, sample);
writer.writeCellsToFile(); writer.writeCellsToFile();
} }
public static void makePlateExp(String cellFile, String filename, Double lambda,
Integer numWells, Integer[] concentrations, Double dropOutRate){
CellFileReader cellReader = new CellFileReader(cellFile);
Plate samplePlate = new Plate(numWells, dropOutRate, concentrations);
samplePlate.fillWellsExponential(cellReader.getFilename(), cellReader.getListOfDistinctCellsDEPRECATED(), lambda);
PlateFileWriter writer = new PlateFileWriter(filename, samplePlate);
writer.writePlateFile();
}
private static void makePlatePoisson(String cellFile, String filename, Integer numWells,
Integer[] concentrations, Double dropOutRate){
CellFileReader cellReader = new CellFileReader(cellFile);
Double stdDev = Math.sqrt(cellReader.getCellCountDEPRECATED());
Plate samplePlate = new Plate(numWells, dropOutRate, concentrations);
samplePlate.fillWells(cellReader.getFilename(), cellReader.getListOfDistinctCellsDEPRECATED(), stdDev);
PlateFileWriter writer = new PlateFileWriter(filename, samplePlate);
writer.writePlateFile();
}
private static void makePlate(String cellFile, String filename, Double stdDev,
Integer numWells, Integer[] concentrations, Double dropOutRate){
CellFileReader cellReader = new CellFileReader(cellFile);
Plate samplePlate = new Plate(numWells, dropOutRate, concentrations);
samplePlate.fillWells(cellReader.getFilename(), cellReader.getListOfDistinctCellsDEPRECATED(), stdDev);
PlateFileWriter writer = new PlateFileWriter(filename, samplePlate);
writer.writePlateFile();
}
private static void matchCDR3s(String graphFile, Integer lowThreshold, Integer highThreshold,
Integer occupancyDifference, Integer overlapPercent) {
}
} }

View File

@@ -20,11 +20,11 @@ public class Plate {
private double lambda; private double lambda;
boolean exponential = false; boolean exponential = false;
public Plate(CellSample cells, String cellFilename, int size, Integer[] populations, public Plate(CellSample cells, String cellFilename, int numWells, Integer[] populations,
double dropoutRate, double stdDev_or_lambda, boolean exponential){ double dropoutRate, double stdDev_or_lambda, boolean exponential){
this.cells = cells; this.cells = cells;
this.sourceFile = cellFilename; this.sourceFile = cellFilename;
this.size = size; this.size = numWells;
this.error = dropoutRate; this.error = dropoutRate;
this.populations = populations; this.populations = populations;
this.exponential = exponential; this.exponential = exponential;