net.maizegenetics.pangenome.processAssemblyGenomes.MummerAnalysisMetricsPlugin Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of phg Show documentation
Show all versions of phg Show documentation
PHG - Practical Haplotype Graph
/**
*
*/
package net.maizegenetics.pangenome.processAssemblyGenomes;
import java.awt.Frame;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import javax.swing.ImageIcon;
import org.apache.log4j.Logger;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Range;
import com.google.common.collect.RangeSet;
import com.google.common.collect.TreeRangeSet;
import net.maizegenetics.dna.map.Chromosome;
import net.maizegenetics.dna.map.GenomeSequence;
import net.maizegenetics.dna.map.GenomeSequenceBuilder;
import net.maizegenetics.pangenome.api.CreateGraphUtils;
import net.maizegenetics.pangenome.api.ReferenceRange;
import net.maizegenetics.pangenome.db_loading.DBLoadingUtils;
import net.maizegenetics.plugindef.AbstractPlugin;
import net.maizegenetics.plugindef.DataSet;
import net.maizegenetics.plugindef.PluginParameter;
import net.maizegenetics.util.Tuple;
import net.maizegenetics.util.Utils;
/**
* This method provides summary statistics on mummer output. The ref and assembly fastas are
* to provide length values.
*
* Assumptions:
* 1. file has been sorted and filtered to contain just 1 chromosome
* 2. User indicates which chrom name in "query (usually assembly)" and "target (usually ref)" parameters
* 3. This file is NOT run on bz region fastas. WIll be a problem with db for ref name vs
* refchrom name in the fasta file - they won't match
*
* Dec 20, 2019: I'm deprecating this plugin as it was written to analyze Mummer
* output when we were deciding which aligner to use. It would still work, though,
* so I don't want to remove it. - But don't want it listed as a plugin for the PHG
* paper.
*
* @author lcj34
*
*/
@Deprecated
public class MummerAnalysisMetricsPlugin extends AbstractPlugin {
private static final Logger myLogger = Logger.getLogger(MummerAnalysisMetricsPlugin.class);
private static final Pattern tab = Pattern.compile("\t");
private PluginParameter coordsFile = new PluginParameter.Builder("coordsFile", null, String.class).guiName("Mummer Coords File").required(true).inFile()
.description("Output of Mummer coords file ").build();
private PluginParameter refFasta = new PluginParameter.Builder("refFasta", null, String.class).guiName("Reference Fasta File").required(true).inFile()
.description("Input reference fasta file ").build();
private PluginParameter assemblyFasta = new PluginParameter.Builder("assemblyFasta", null, String.class).guiName("Assembly Fasta File").required(true).inFile()
.description("Input Assembly fasta file used for aligning").build();
private PluginParameter query = new PluginParameter.Builder("query", null, String.class).guiName("Query name ").required(true)
.description("Name of assembly in mummer query, this is the chromName").build();
private PluginParameter target = new PluginParameter.Builder("target", null, String.class).guiName("Target name").required(true)
.description("Name of target in mummer query, this is usually the ref chrom").build();
private PluginParameter mummerParams = new PluginParameter.Builder("mummerParams", null, String.class).guiName("Mummer Parameters").required(true)
.description("Mummer parameters used").build();
private PluginParameter prefix = new PluginParameter.Builder("prefix", null, String.class).guiName("Output File prefix").required(true)
.description("Name to prefix to output results file").build();
private PluginParameter outputDir = new PluginParameter.Builder("outputDir", null, String.class).guiName("Output Directory").required(true).outDir()
.description("Output directory including trailing / for writing files").build();
private PluginParameter configFile = new PluginParameter.Builder("configFile", null, String.class).guiName("DB Config File").required(true).inFile()
.description("File containing lines with data for host=, user=, password= and DB=, DBtype= used for db connection").build();
private PluginParameter asmBZStart = new PluginParameter.Builder("asmBZStart", null, Integer.class).guiName("BZ Assembly Start").required(true)
.description("Start position for bz region on the assembly").build();
private PluginParameter asmBZEnd = new PluginParameter.Builder("asmBZEnd", null, Integer.class).guiName("BZ Assembly End").required(true)
.description("End position for bz region on the assembly").build();
public MummerAnalysisMetricsPlugin() {
super(null, false);
}
public MummerAnalysisMetricsPlugin(Frame parentFrame) {
super(parentFrame, false);
}
public MummerAnalysisMetricsPlugin(Frame parentFrame, boolean isInteractive) {
super(parentFrame, isInteractive);
}
@Override
public DataSet processData(DataSet input) {
RangeSet refCoordSet = TreeRangeSet.create();
RangeSet asmCoordSet = TreeRangeSet.create();
GenomeSequence refSeq = GenomeSequenceBuilder.instance(refFasta());
GenomeSequence asmSeq = GenomeSequenceBuilder.instance(assemblyFasta());
// Hard-coded for now - should be parameters
Range bzB73 = Range.closed(11147252, 11220492);
Range bzPH207 = Range.closed(asmBZStart(), asmBZEnd());
// CHrom sizes
int refChromSize = refSeq.chromosomeSize(Chromosome.instance(target()));
int asmChromSize = asmSeq.chromosomeSize(Chromosome.instance(query()));
System.out.println("Begin coords file processing");
double totalPercentID = 0;
String fullChromSummary = outputDir() + "/" + prefix() + "_metrics.txt";
try (BufferedReader br = Utils.getBufferedReader(coordsFile());
BufferedWriter bw = Utils.getBufferedWriter(fullChromSummary)) {
int headerCount = 0;
int valueCount = 0;
String line = null;
String refChrom = "none";
String asmChrom = "none";
while ((line = br.readLine()) != null) {
headerCount++;
if (headerCount < 6) {
System.out.println("Skipping line:" + line);
continue; // skipping 5 lines of header
}
valueCount++;
String[] tokens = tab.split(line);
// mummer coords with created with the -T flags has 4 header lines, then these columns:
// S1 E1 S2 E2 [LEN 1] {LEN 2] {%id] chr1 chr2
// All values are integers, but the "|" shows up on each line
System.out.println("Proessing line: " + line );
// RangeSet coalesce the ranges, which is what I want
int refStart = Integer.parseInt(tokens[0]);
int refEnd = Integer.parseInt(tokens[1]);
// If the end is < start, it mapped on reverse strand.
// These are not reverse strand coordinates with the revverse starting at 0
// If it were, I'd do this:
// To get on the positive strand:
// chromSize - end = start.
// chromSize - start = end;
// But instead, I just flip them
if (refStart > refEnd) {
int tempStart = refEnd;
refEnd = refStart;
refStart = tempStart;
}
refCoordSet.add(Range.closed(refStart,refEnd));
int queryStart = Integer.parseInt(tokens[2]);
int queryEnd = Integer.parseInt(tokens[3]);
if (queryStart > queryEnd) {
int tempStart = queryEnd;
queryEnd = queryStart;
queryStart = tempStart;
}
asmCoordSet.add(Range.closed(queryStart, queryEnd));
// add %ID to use in creating average
double id = Double.parseDouble(tokens[6]);
totalPercentID += id;
refChrom = tokens[7]; // these snouldn't change
asmChrom = tokens[8];
}
System.out.println("Coords file processed, read fasta files for processing");
// Values have been read in. Calculate percentages.
double aveIdentityForChrom = totalPercentID/valueCount;
// Get total number of bases aligned
int totalRefBasesAligned = getNumAlignedBases(refCoordSet);
int totalAsmBasesAligned = getNumAlignedBases(asmCoordSet);
// Calculate bz region coverage
Tuple bzB73Coverage;
Tuple bzPH207Coverage;
if (refChrom.equals("9")) { // this is only relevant for chrom 9 processing
bzB73Coverage = getRegionCoverage(refCoordSet,bzB73);
bzPH207Coverage = getRegionCoverage(asmCoordSet, bzPH207);
} else {
bzB73Coverage = new Tuple(0,0.0);
bzPH207Coverage = new Tuple(0,0.0);
}
// Calculate percentage of chromosomes aligned
System.out.println("Total refBases aligned " + totalRefBasesAligned + ", refchromSize: " + refChromSize);
double refPercentAligned = ((double)(totalRefBasesAligned)/refChromSize) * 100 ;
System.out.println("Total asmBases aligned " + totalAsmBasesAligned + ", asmChromSize: " + asmChromSize);
double asmPercentAligned = ((double)(totalAsmBasesAligned)/asmChromSize) * 100;
System.out.println("refPercentAligned: " + refPercentAligned + ", asmPercentAligned: " + asmPercentAligned);
// Get db connection to grab anchor info
System.out.println("Get db connection ...");
Connection connection = DBLoadingUtils.connection(configFile(),false);
if (connection == null) {
System.out.println("\n COuld not get connection for config file db");
throw new IllegalStateException ("MummerAnalysisMetricsPlugin: could not get db connection from configFile " + configFile() );
}
System.out.println("Get refRangesForChrom");
// get anchorID, ReferenceRanges for this chromosome
Map idToRefRangeMap = refRangesForChrom( connection, refChrom);
// Split RefRangeMap above into a RangeSet of anchor coordinates
RangeSet refAnchorSet = getRangesForChrom(idToRefRangeMap, Chromosome.instance(refChrom), DBLoadingUtils.AnchorType.ANCHOR);
int numAnchors = refAnchorSet.asRanges().size();
int numAnchorsRepresented = 0;
System.out.println("Size of refAnchorSet: " + numAnchors);
// See which ranges are covered
for (Range anchorRange : refAnchorSet.asRanges()) {
RangeSet numberSubRangeSet = refCoordSet.subRangeSet(Range.closed(anchorRange.lowerEndpoint(), anchorRange.upperEndpoint()));
if (!numberSubRangeSet.isEmpty()) {
numAnchorsRepresented++;
}
}
double percentAnchorsRepresented = (double)(numAnchorsRepresented * 100)/numAnchors;
// Get map of inter-anchor for this chrom
RangeSet refInterAnchorSet = getRangesForChrom(idToRefRangeMap, Chromosome.instance(refChrom), DBLoadingUtils.AnchorType.INTER_ANCHOR);
int numInterAnchors = refInterAnchorSet.asRanges().size();
int numInterAnchorsRepresented = 0;
System.out.println("Size of refInterAnchorSet: " + numInterAnchors);
// See which ranges are covered
for (Range interAnchorRange : refInterAnchorSet.asRanges()) {
RangeSet numberSubRangeSet = refCoordSet.subRangeSet(Range.closed(interAnchorRange.lowerEndpoint(), interAnchorRange.upperEndpoint()));
if (!numberSubRangeSet.isEmpty()) {
numInterAnchorsRepresented++;
}
}
double percentInterAnchorsRepresented = (double)(numInterAnchorsRepresented * 100)/numInterAnchors;
System.out.println("Writing to metrics file");
// Write metrics
String outputHeader = "refChrom\tasmChrom\tMummer params\t%Ref aligned\t%%asm Aligned\tAverage Identity\t"
+ "Number of Anchors in Chrom\tNumber of Anchors Represented\t% Anchors represented\t"
+ "Number of InterAnchors In Chrom\tNumber of InterAnchorsRepresented\t% Interanchors_Represented\t"
+ "%Ref BZ Region covered\t%ASM BZ Region Covered\n";
bw.write(outputHeader);
StringBuilder metricsSB = new StringBuilder();
metricsSB.append(refChrom).append("\t");
metricsSB.append(asmChrom).append("\t");
metricsSB.append(mummerParams()).append("\t");
metricsSB.append(refPercentAligned).append("\t");
metricsSB.append(asmPercentAligned).append("\t");
metricsSB.append(aveIdentityForChrom).append("\t");
metricsSB.append(numAnchors).append("\t");
metricsSB.append(numAnchorsRepresented).append("\t");
metricsSB.append(percentAnchorsRepresented).append("\t");
metricsSB.append(numInterAnchors).append("\t");
metricsSB.append(numInterAnchorsRepresented).append("\t");
metricsSB.append(percentInterAnchorsRepresented).append("\t");
metricsSB.append(bzB73Coverage.y).append("\t");
metricsSB.append(bzPH207Coverage.y).append("\n");
bw.write(metricsSB.toString());
System.out.println("FINished processing metrics file ");
} catch (IOException ioe) {
throw new IllegalArgumentException("Error reading coords file " + coordsFile() + " " + ioe.getMessage());
} catch (NumberFormatException nfe) {
nfe.printStackTrace();
throw new IllegalArgumentException("Error converting coordiates file entry to integer from coordsFile " + coordsFile() + " " + nfe.getMessage());
} catch (Exception exc) {
exc.printStackTrace();
throw new IllegalArgumentException("Error processing mummer statistics: " + exc.getMessage());
}
System.out.println("DONE");
return null;
}
// Counts the ranges - assumes a set of "closed" ranges (inclusive/inclusive endpoints)
public int getNumAlignedBases(RangeSet asmCoordSet){
int totalBasesAligned = 0;
for (Range range : asmCoordSet.asRanges()) {
int numberInRange = (range.upperEndpoint() - range.lowerEndpoint()) + 1; // these are closed ranges
totalBasesAligned += numberInRange;
}
return totalBasesAligned;
}
// THe method takes a RangeSet of integers, and a single range. It finds all
// the ranges in the set that intersect the targetRange.
// Calculate both the number of bases from the targetRange that are represented
// in the rangeSet, and the percentage of the bases represented. Return a Tuple with
// this information.
public Tuple getRegionCoverage(RangeSet rangeSet, Range targetRange) {
int rangeSize = (targetRange.upperEndpoint() - targetRange.lowerEndpoint()) +1;
// This just gives overlaps, which is what we want.
// Not looking for the exact ranges in the set, but rather the number of positionss
// from the targetRange that are included in the rangeSet
RangeSet numberSubRangeSet = rangeSet.subRangeSet(targetRange);
int numBases = 0;
for (Range range : numberSubRangeSet.asRanges()) {
System.out.println("value: " + range.lowerEndpoint() + ":" + range.upperEndpoint());
numBases += ((range.upperEndpoint() - range.lowerEndpoint()) +1);
}
double percentRangeCovered = ((double)(numBases)/rangeSize) * 100 ;
return new Tuple(numBases,percentRangeCovered);
}
public Map refRangesForChrom(Connection dbConn, String chrom) {
// Create method name for querying initial ref region and inter-region ref_range_group method ids
String refLine = CreateGraphUtils.getRefLineName( dbConn);
String refMethodName = DBLoadingUtils.REGION_REFERENCE_RANGE_GROUP;
String refInterMethodName = DBLoadingUtils.INTER_REGION_REFERENCE_RANGE_GROUP;
List refGrpMethodsList = new ArrayList();
int refGrpMethodID = CreateGraphUtils.methodId(dbConn, refMethodName);
int refInterGrpMethodID = CreateGraphUtils.methodId(dbConn, refInterMethodName);
// Add method Ids to list if valid. There are not always inter-group methods in the db
if (refGrpMethodID > 0) refGrpMethodsList.add(Integer.toString(refGrpMethodID));
if (refInterGrpMethodID > 0) refGrpMethodsList.add(Integer.toString(refInterGrpMethodID));
String refGrpMethodString = refGrpMethodsList.stream().collect(Collectors.joining(","));
// query anchors, filter on chrom/version. This gets focus AND non-focus as the latter will be
// needed later.
// Query based on methodIds created above
String query = "select reference_ranges.ref_range_id, chrom,range_start,range_end, methods.name " +
" from reference_ranges, ref_range_ref_range_group,ref_range_groups, methods " +
" where reference_ranges.ref_range_id=ref_range_ref_range_group.ref_range_id " +
" AND ref_range_groups.ref_range_group_id = ref_range_ref_range_group.ref_range_group_id " +
" AND ref_range_groups.group_method_id = methods.method_id " +
" AND methods.method_type = " + DBLoadingUtils.MethodType.REF_RANGE_GROUP.getValue() +
" AND chrom='" + chrom + "';";
myLogger.info("referenceRangesAsMap: query statement: " + query);
ImmutableMap.Builder builder = ImmutableMap.builder();
try (ResultSet rs = dbConn.createStatement().executeQuery(query)) {
while (rs.next()) {
int id = rs.getInt("ref_range_id");
String chromosome = rs.getString("chrom");
int start = rs.getInt("range_start");
int end = rs.getInt("range_end");
String methodName = rs.getString("name");
builder.put(id, new ReferenceRange("B73Ref", Chromosome.instance(chromosome), start, end, id, methodName));
}
} catch (Exception se) {
myLogger.debug(se.getMessage(), se);
throw new IllegalStateException("CreateGraphUtils: referenceRanges: Problem querying the database: " + se.getMessage());
}
Map result = builder.build();
return result;
}
// Returns a range set from the referenceRangeMap. If "anchor" is true, only
// return the anchor. If "false", return interanchors
public static RangeSet getRangesForChrom(Map refRangeMap, Chromosome chrom, DBLoadingUtils.AnchorType anchorType) {
RangeSet anchorRangeSet = TreeRangeSet.create();
for (ReferenceRange refRange : refRangeMap.values()) {
if (!(refRange.chromosome().equals(chrom))) continue; // skip anchors for other chroms
if (anchorType == DBLoadingUtils.AnchorType.ANCHOR || anchorType == DBLoadingUtils.AnchorType.BOTH) {
//if (refRange.isAnchor()) anchorRangeSet.add(Range.closed(refRange.start(), refRange.end()));
} else if (anchorType == DBLoadingUtils.AnchorType.INTER_ANCHOR || anchorType == DBLoadingUtils.AnchorType.BOTH) {
//if (!refRange.isAnchor())anchorRangeSet.add(Range.closed(refRange.start(), refRange.end()));
}
}
System.out.println("getRangesForChrom: anchorType : " + anchorType + ", anchorRangeSet size: " + anchorRangeSet.asRanges().size());
return anchorRangeSet;
}
/**
* @param args
*/
public static void main(String[] args) {
String lynnBaseDir = "/Users/lcj34/notes_files/phg_2018/assembly_testing/mummer/metrics/";
//GeneratePluginCode.generate(MummerAnalysisMetricsPlugin.class);
// String coordsFile = lynnBaseDir + "b73ph207_chr9_withC1000flag.coords";
// String refFasta = lynnBaseDir + "b73chr9.fa";
// String asmFasta = lynnBaseDir + "ph207chr9.fasta";
// String target = "9";
// String query = "09";
// String mummerParams = "-c 1000";
// String prefix = "b73ph207_chr9_withc1000";
// String config = "/Users/lcj34/notes_files/phg_2018/assembly_testing/mummer/configSQLite.txt";
// String outputDir = lynnBaseDir;
if (args.length != 11) {
System.out.println("Expecting 11 parameters in this order: ");
System.out.println(" cordsFile name");
System.out.println(" Path to ref Fasta ");
System.out.println(" Path to assmebly fasta");
System.out.println(" Target chrom name (this is ref chrom name)");
System.out.println(" Query chrom name (this is query chrom name)");
System.out.println(" String of Mummer parameters used");
System.out.println(" Prefix to append to output file as name");
System.out.println(" Path to config file for connecting to DB");
System.out.println(" assembly bz region start");
System.out.println(" assembly bz region end");
System.out.println(" Path to output Directory for metrics file");
System.out.println(" Please fix parameters and try again.");
return;
}
String coordsFile = args[0];
String refFasta = args[1];
String asmFasta = args[2];
String target = args[3];
String query = args[4];
String mummerParams = args[5];
String prefix = args[6];
String config = args[7];
int bzStart = Integer.parseInt(args[8]);
int bzEnd = Integer.parseInt(args[9]);
String outputDir = args[10];
new MummerAnalysisMetricsPlugin()
.coordsFile(coordsFile)
.refFasta(refFasta)
.assemblyFasta(asmFasta)
.mummerParams(mummerParams)
.prefix(prefix)
.query(query)
.target(target)
.configFile(config)
.asmBZStart(bzStart)
.asmBZEnd(bzEnd)
.outputDir(outputDir)
.performFunction(null);
}
@Override
public ImageIcon getIcon() {
return null;
}
@Override
public String getButtonName() {
// TODO Auto-generated method stub
return null;
}
@Override
public String getToolTipText() {
// TODO Auto-generated method stub
return null;
}
/**
* Output of Mummer coords file
*
* @return Mummer Coords File
*/
public String coordsFile() {
return coordsFile.value();
}
/**
* Set Mummer Coords File. Output of Mummer coords file
*
*
* @param value Mummer Coords File
*
* @return this plugin
*/
public MummerAnalysisMetricsPlugin coordsFile(String value) {
coordsFile = new PluginParameter<>(coordsFile, value);
return this;
}
/**
* Input reference fasta file
*
* @return Reference Fasta File
*/
public String refFasta() {
return refFasta.value();
}
/**
* Set Reference Fasta File. Input reference fasta file
*
*
* @param value Reference Fasta File
*
* @return this plugin
*/
public MummerAnalysisMetricsPlugin refFasta(String value) {
refFasta = new PluginParameter<>(refFasta, value);
return this;
}
/**
* Assembly fasta file used when aligning
*
* @return Assembly Fasta File
*/
public String assemblyFasta() {
return assemblyFasta.value();
}
/**
* Set Assembly Genome File. Assembly fasta file used
* when aligning
*
* @param value Assembly Genome File
*
* @return this plugin
*/
public MummerAnalysisMetricsPlugin assemblyFasta(String value) {
assemblyFasta = new PluginParameter<>(assemblyFasta, value);
return this;
}
/**
* Name of assembly in mummer query, this is usually the
* assembly
*
* @return Query name
*/
public String query() {
return query.value();
}
/**
* Set Query name . Name of assembly in mummer query,
* this is usually the assembly
*
* @param value Query name
*
* @return this plugin
*/
public MummerAnalysisMetricsPlugin query(String value) {
query = new PluginParameter<>(query, value);
return this;
}
/**
* Name of target in mummer query, this is usually the
* reference
*
* @return Target name
*/
public String target() {
return target.value();
}
/**
* Set Target name. Name of target in mummer query, this
* is usually the reference
*
* @param value Target name
*
* @return this plugin
*/
public MummerAnalysisMetricsPlugin target(String value) {
target = new PluginParameter<>(target, value);
return this;
}
/**
* Parameters used when running mummer
*
* @return Value of Mummer parameters
*/
public String mummerParams() {
return mummerParams.value();
}
/**
* Set Mummer Parameters. Value of parameters used when
* running mummer
*
* @param value Mummer parameters
*
* @return this plugin
*/
public MummerAnalysisMetricsPlugin mummerParams(String value) {
mummerParams = new PluginParameter<>(mummerParams, value);
return this;
}
/**
* Name to prefix to output results file
*
* @return Output File refix
*/
public String prefix() {
return prefix.value();
}
/**
* Set Output File refix. Name to prefix to output results
* file
*
* @param value Output File refix
*
* @return this plugin
*/
public MummerAnalysisMetricsPlugin prefix(String value) {
prefix = new PluginParameter<>(prefix, value);
return this;
}
/**
* Output directory including trailing / for writing files
*
* @return Output Directory
*/
public String outputDir() {
return outputDir.value();
}
/**
* Set Output Directory. Output directory including trailing
* / for writing files
*
* @param value Output Directory
*
* @return this plugin
*/
public MummerAnalysisMetricsPlugin outputDir(String value) {
outputDir = new PluginParameter<>(outputDir, value);
return this;
}
/**
* File containing lines with data for host=, user=, password=
* and DB=, DBtype= used for db connection
*
* @return DB Config File
*/
public String configFile() {
return configFile.value();
}
/**
* Set DB Config File. File containing lines with data
* for host=, user=, password= and DB=, DBtype= used for
* db connection
*
* @param value DB Config File
*
* @return this plugin
*/
public MummerAnalysisMetricsPlugin configFile(String value) {
configFile = new PluginParameter<>(configFile, value);
return this;
}
/**
* Start position for bz region on the assembly
*
* @return BZ Assembly Start
*/
public Integer asmBZStart() {
return asmBZStart.value();
}
/**
* Set BZ Assembly Start. Start position for bz region
* on the assembly
*
* @param value BZ Assembly Start
*
* @return this plugin
*/
public MummerAnalysisMetricsPlugin asmBZStart(Integer value) {
asmBZStart = new PluginParameter<>(asmBZStart, value);
return this;
}
/**
* End position for bz region on the assembly
*
* @return BZ Assembly End
*/
public Integer asmBZEnd() {
return asmBZEnd.value();
}
/**
* Set BZ Assembly End. End position for bz region on
* the assembly
*
* @param value BZ Assembly End
*
* @return this plugin
*/
public MummerAnalysisMetricsPlugin asmBZEnd(Integer value) {
asmBZEnd = new PluginParameter<>(asmBZEnd, value);
return this;
}
}