/* * Parameter.java * * Copyright (c) 2002-2015 Alexei Drummond, Andrew Rambaut and Marc Suchard * * This file is part of BEAST. * See the NOTICE file distributed with this work for additional * information regarding copyright ownership and licensing. * * BEAST is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * BEAST is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with BEAST; if not, write to the * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, * Boston, MA 02110-1301 USA */ package dr.app.beauti.options; import dr.app.beauti.types.PriorScaleType; import dr.app.beauti.types.PriorType; import dr.math.distributions.Distribution; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.Map; /** * @author Andrew Rambaut * @author Alexei Drummond */ public class Parameter implements Serializable { private static final long serialVersionUID = -8008521511485034329L; public static final double UNIFORM_MAX_BOUND = 1.0E100; private String prefix = null; private boolean priorEdited; private boolean meanInRealSpace = false; // Required para private String baseName; private final String description; private int dimensionWeight = 1; private final List<Parameter> subParameters = new ArrayList<Parameter>(); // final Builder para public String taxaId; // needs to change TMRCA stat name. Issue 520 public final boolean isNodeHeight; public final boolean isStatistic; public final boolean isDiscrete; public final boolean isHierarchical; public final boolean isCMTCRate; public final boolean isNonNegative; public final boolean isMaintainedSum; public final boolean isZeroOne; public final boolean isCached; public final boolean isAdaptiveMultivariateCompatible; public boolean isCalibratedYule = false; // public final double lower; // public final double upper; private PartitionOptions options; public final PriorScaleType scaleType; public final boolean isPriorFixed; public PriorType priorType; private Parameter parent; public double getInitial() { return initial; } public void setInitial(double initial) { this.initial = initial; } // Editable fields private boolean isFixed; private double initial; public double maintainedSum; public boolean isTruncated; public double truncationUpper; public double truncationLower; public double mean; public double stdev; public double shape; public double shapeB; public double scale; public double offset; public double precision; public double uniformUpper; public double uniformLower; public boolean isLinked; public String linkedName; public static class Builder { // Required para private final String baseName; private final String description; // Optional para - initialized to default values private PriorScaleType scaleType = PriorScaleType.NONE; private String taxaId = null; private boolean isNodeHeight = false; private boolean isDiscrete = false; private boolean isHierarchical = false; private boolean isCMTCRate = false; private boolean isNonNegative = false; private boolean isZeroOne = false; private boolean isMaintainedSum = false; private boolean isStatistic = false; private boolean isCached = false; private PartitionOptions options = null; private PriorType priorType = PriorType.NONE_TREE_PRIOR; private boolean isPriorFixed = false; private boolean isAdaptiveMultivariateCompatible = false; private double maintainedSum = 1.0; private double initial = Double.NaN; // private double upper = Double.NaN; // private double lower = Double.NaN; private boolean isTruncated = false; public double truncationUpper = Double.POSITIVE_INFINITY; public double truncationLower = Double.NEGATIVE_INFINITY; public double mean = 0.0; public double stdev = 1.0; public double shape = 1.0; public double shapeB = 3.0; public double scale = 1.0; public double offset = 0.0; public double precision = 1.0; // the uniform distribution has explicit bounds (ignores the truncations): public double uniformUpper = UNIFORM_MAX_BOUND; public double uniformLower = -UNIFORM_MAX_BOUND; private boolean isFixed = false; public Builder(String name, String description) { this.baseName = name; this.description = description; } public Builder duplicate(Parameter source) { scaleType = source.scaleType; taxaId = source.taxaId; isNodeHeight = source.isNodeHeight; isDiscrete = source.isDiscrete; isHierarchical = source.isHierarchical; isCMTCRate = source.isCMTCRate; isNonNegative = source.isNonNegative; isZeroOne = source.isZeroOne; isMaintainedSum = source.isMaintainedSum; isStatistic = source.isStatistic; isCached = source.isCached; options = source.options; priorType = source.priorType; isPriorFixed = source.isPriorFixed; isAdaptiveMultivariateCompatible = source.isAdaptiveMultivariateCompatible; initial = source.initial; maintainedSum = source.maintainedSum; isTruncated = source.isTruncated; truncationUpper = source.truncationUpper; truncationLower = source.truncationLower; mean = source.mean; stdev = source.stdev; shape = source.shape; shapeB = source.shapeB; scale = source.scale; offset = source.offset; precision = source.precision; uniformUpper = source.uniformUpper; uniformLower = source.uniformLower; isFixed = source.isFixed; return this; } public Builder scaleType(PriorScaleType scaleType) { this.scaleType = scaleType; return this; } public Builder initial(double initial) { this.initial = initial; return this; } public Builder maintainedSum(double maintainedSum) { this.maintainedSum = maintainedSum; this.isMaintainedSum = true; return this; } public Builder taxaId(String taxaId) { this.taxaId = taxaId; return this; } public Builder isNodeHeight(boolean isNodeHeight) { this.isNodeHeight = isNodeHeight; return this; } public Builder isCached(boolean isCached) { this.isCached = isCached; return this; } public Builder isStatistic(boolean isStatistic) { this.isStatistic = isStatistic; return this; } public Builder partitionOptions(PartitionOptions options) { this.options = options; return this; } public Builder prior(PriorType priorType) { this.priorType = priorType; return this; } public Builder isDiscrete(boolean isDiscrete) { this.isDiscrete = isDiscrete; return this; } public Builder isHierarchical(boolean isHierarchical) { this.isHierarchical = isHierarchical; return this; } public Builder isNonNegative(boolean isNonNegative) { this.isNonNegative = isNonNegative; if (isNonNegative) { this.uniformLower = 0.0; } return this; } public Builder isZeroOne(boolean isZeroOne) { this.isZeroOne = isZeroOne; if (isZeroOne) { this.uniformLower = 0.0; this.uniformUpper = 1.0; } return this; } public Builder isMaintainedSum(boolean isMaintainedMean) { this.isMaintainedSum = isMaintainedMean; return this; } public Builder isAdaptiveMultivariateCompatible(boolean isAdaptiveMultivariateCompatible) { this.isAdaptiveMultivariateCompatible = isAdaptiveMultivariateCompatible; return this; } public Builder isCMTCRate(boolean isCMTCRate) { this.isCMTCRate = isCMTCRate; return this; } public Builder isFixed(boolean isFixed) { this.isFixed = isFixed; return this; } public Builder isPriorFixed(boolean priorFixed) { this.isPriorFixed = priorFixed; return this; } public Builder uniformUpper(double upper) { this.uniformUpper = upper; return this; } public Builder uniformLower(double lower) { this.uniformLower = lower; return this; } public Builder truncationUpper(double truncationUpper) { this.isTruncated = true; this.truncationUpper = truncationUpper; return this; } public Builder truncationLower(double truncationLower) { this.isTruncated = true; this.truncationLower = truncationLower; return this; } public Builder mean(double mean) { this.mean = mean; return this; } public Builder stdev(double stdev) { this.stdev = stdev; return this; } public Builder precision(double precision) { this.precision = precision; return this; } public Builder shape(double shape) { this.shape = shape; return this; } public Builder shapeB(double shapeB) { this.shapeB = shapeB; return this; } public Builder scale(double scale) { this.scale = scale; return this; } public Builder offset(double offset) { this.offset = offset; return this; } public Parameter build() { return new Parameter(this); } public Parameter build(Map<String, Parameter> map) { final Parameter parameter = new Parameter(this); map.put(baseName, parameter); return parameter; } } private Parameter(Builder builder) { baseName = builder.baseName; description = builder.description; scaleType = builder.scaleType; initial = builder.initial; maintainedSum = builder.maintainedSum; taxaId = builder.taxaId; isNodeHeight = builder.isNodeHeight; isStatistic = builder.isStatistic; isCached = builder.isCached; options = builder.options; priorType = builder.priorType; isDiscrete = builder.isDiscrete; isFixed = builder.isFixed; isHierarchical = builder.isHierarchical; isCMTCRate = builder.isCMTCRate; isNonNegative = builder.isNonNegative; isZeroOne = builder.isZeroOne; isMaintainedSum = builder.isMaintainedSum; isPriorFixed = builder.isPriorFixed; isAdaptiveMultivariateCompatible = builder.isAdaptiveMultivariateCompatible; // upper = builder.upper; // lower = builder.lower; isTruncated = builder.isTruncated; truncationUpper = builder.truncationUpper; truncationLower = builder.truncationLower; mean = builder.mean; stdev = builder.stdev; shape = builder.shape; shapeB = builder.shapeB; scale = builder.scale; offset = builder.offset; uniformUpper = builder.uniformUpper; uniformLower = builder.uniformLower; // ExponentialDistribution(1.0 / mean) if (priorType == PriorType.EXPONENTIAL_PRIOR && mean == 0) mean = 1; if (priorType == PriorType.LOGNORMAL_PRIOR && meanInRealSpace && mean <= 0) mean = 0.01; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++ public void setPrefix(String prefix) { this.prefix = prefix; } private String getFullName() { if (prefix != null) return prefix + getBaseName(); return getBaseName(); } public String getBaseName() { if (taxaId != null) { return taxaId; // do not why use taxaId for tmrca, they seems duplicated } return baseName; } public String getName() { if (taxaId != null) { return "tmrca(" + getFullName() + ")"; } else { return getFullName(); } } public void setName(String name) { this.baseName = name; } public String getXMLName() { // only for BeautiTemplate if (taxaId != null) { return "tmrca_" + getFullName(); } else { return getFullName(); } } public String getDescription() { if (taxaId != null && options != null) { return description + " on tree " + options.getName(); } return description; } public double getPriorExpectationMean() { double expMean = 1.0; Distribution dist = priorType.getDistributionInstance(this); if (dist != null) { expMean = dist.mean(); if (expMean == 0) { expMean = dist.quantile(0.975); } if (expMean == 0) { expMean = 1.0; } } return expMean; } public PartitionOptions getOptions() { return options; } public void setOptions(PartitionOptions options) { // need to set, which keeps consistent to taxonSetsTreeModel this.options = options; } public void setPriorEdited(boolean priorEdited) { this.priorEdited = priorEdited; } public boolean isPriorEdited() { return priorEdited; } public boolean isPriorImproper() { if ( // 1/x is an improper prior but we probably don't want to flag it as // such (or we want to make a more explicit distinction about when it // might be appropriate: /* priorType == PriorType.ONE_OVER_X_PRIOR || */ (priorType == PriorType.NONE_IMPROPER) || (priorType == PriorType.UNIFORM_PRIOR && (Double.isInfinite(getLowerBound()) || Double.isInfinite(getUpperBound())))) { return true; } return false; } public double getLowerBound() { double lower = Double.NEGATIVE_INFINITY; if (priorType == PriorType.UNIFORM_PRIOR) { lower = uniformLower; } if (isNonNegative || isZeroOne) { if (lower < 0) lower = 0.0; } if (isTruncated && !Double.isInfinite(truncationLower)) { lower = truncationLower; } return lower; } public double getUpperBound() { double upper = Double.POSITIVE_INFINITY; if (isZeroOne) { if (upper > 1) { upper = 1.0; } } if (priorType == PriorType.UNIFORM_PRIOR) { upper = uniformUpper; } if (isTruncated && !Double.isInfinite(truncationUpper)) { upper = truncationUpper; } return upper; } public boolean isFixed() { return priorType == PriorType.NONE_FIXED; } public void setFixed(boolean isFixed) { if (isFixed) { priorType = PriorType.NONE_FIXED; } } public boolean isMeanInRealSpace() { return meanInRealSpace; } public void setMeanInRealSpace(boolean meanInRealSpace) { this.meanInRealSpace = meanInRealSpace; } public int[] getParameterDimensionWeights() { // if (getOptions() != null && getOptions() instanceof PartitionSubstitutionModel) { // return ((PartitionSubstitutionModel)getOptions()).getPartitionCodonWeights(); // } if (getSubParameters().size() > 0) { int[] weights = new int[getSubParameters().size()]; for (int i = 0; i < weights.length; i++) { weights[i] = getSubParameters().get(i).getDimensionWeight(); } return weights; } return new int[] { dimensionWeight }; } public int getDimensionWeight() { return dimensionWeight; } public void setDimensionWeight(int dimensionWeight) { this.dimensionWeight = dimensionWeight; } public void setParent(Parameter parent) { this.parent = parent; } public Parameter getParent() { return parent; } public void addSubParameter(Parameter parameter) { parameter.setParent(this); subParameters.add(parameter); } public void clearSubParameters() { subParameters.clear(); } public List<Parameter> getSubParameters() { return subParameters; } @Override public String toString() { return getName(); } }