/* * PartitionOptions.java * * Copyright (c) 2002-2012 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.evolution.datatype.DataType; import dr.math.MathUtils; import java.util.List; /** * @author Alexei Drummond * @author Andrew Rambaut * @author Walter Xie */ public abstract class PartitionOptions extends ModelOptions { protected String partitionName; protected final BeautiOptions options; protected double[] avgRootAndRate = new double[]{1.0, 1.0}; public PartitionOptions(BeautiOptions options) { this.options = options; } public PartitionOptions(BeautiOptions options, String name) { this.options = options; this.partitionName = name; initModelParametersAndOpererators(); } protected abstract void initModelParametersAndOpererators(); protected abstract void selectParameters(List<Parameter> params); protected abstract void selectOperators(List<Operator> ops); public abstract String getPrefix(); // protected void createParameterClockRateUndefinedPrior(PartitionOptions options, String name, String description, PriorScaleType scaleType, // double initial, double truncationLower, double truncationUpper) { // it will change to Uniform // new Parameter.Builder(name, description).scaleType(scaleType).prior(PriorType.UNDEFINED).initial(initial) // .isCMTCRate(true).isNonNegative(true) // .truncationLower(truncationLower).truncationUpper(truncationUpper).partitionOptions(options).build(parameters); // } // // protected void createParameterClockRateReferencePrior(PartitionOptions options, String name, String description, PriorScaleType scaleType, // double initial) { // it will change to Uniform // new Parameter.Builder(name, description).scaleType(scaleType).prior(PriorType.CMTC_RATE_REFERENCE_PRIOR).initial(initial) // .isCMTCRate(true).isNonNegative(true) // .truncationLower(truncationLower).truncationUpper(truncationUpper).partitionOptions(options).build(parameters); // } // // protected void createParameterClockRateUniform(PartitionOptions options, String name, String description, PriorScaleType scaleType, // double initial, double truncationLower, double truncationUpper) { // new Parameter.Builder(name, description).scaleType(scaleType).prior(PriorType.UNIFORM_PRIOR).initial(initial) // .isCMTCRate(true).isNonNegative(true) // .truncationLower(truncationLower).truncationUpper(truncationUpper).partitionOptions(options).build(parameters); // } // // protected void createParameterClockRateGamma(PartitionOptions options, String name, String description, PriorScaleType scaleType, // double initial, double shape, double scale) { // new Parameter.Builder(name, description).scaleType(scaleType).prior(PriorType.GAMMA_PRIOR).initial(initial) // .isCMTCRate(true).isNonNegative(true) // .shape(shape).scale(scale).partitionOptions(options).build(parameters); // } // // public void createParameterClockRateExponential(PartitionOptions options, String name, String description, PriorScaleType scaleType, // double initial, double mean, double offset) { // new Parameter.Builder(name, description).scaleType(scaleType).prior(PriorType.EXPONENTIAL_PRIOR) // .isCMTCRate(true).isNonNegative(true) // .initial(initial).mean(mean).offset(offset).partitionOptions(options).build(parameters); // } // // protected void createParameterTree(PartitionOptions options, String name, String description, boolean isNodeHeight, double value) { new Parameter.Builder(name, description).isNodeHeight(isNodeHeight).scaleType(PriorScaleType.TIME_SCALE) .isNonNegative(true).initial(value).partitionOptions(options).build(parameters); } protected void createAllMusParameter(PartitionOptions options, String name, String description) { new Parameter.Builder(name, description).partitionOptions(options).build(parameters); } public Parameter getParameter(String name) { Parameter parameter = parameters.get(name); if (parameter == null) { throw new IllegalArgumentException("Parameter with name, " + name + ", is unknown"); } parameter.setPrefix(getPrefix()); autoScale(parameter); // not include clock rate, and treeModel.rootHeight return parameter; } public Operator getOperator(String name) { Operator operator = operators.get(name); if (operator == null) throw new IllegalArgumentException("Operator with name, " + name + ", is unknown"); operator.setPrefix(getPrefix()); return operator; } public String getName() { return partitionName; } public void setName(String name) { this.partitionName = name; } public String toString() { return getName(); } public DataType getDataType() { return options.getDataPartitions(this).get(0).getDataType(); } public double[] getAvgRootAndRate() { return avgRootAndRate; } public void setAvgRootAndRate() { this.avgRootAndRate = options.clockModelOptions.calculateInitialRootHeightAndRate(options.getDataPartitions(this)); } protected void autoScale(Parameter param) { double avgInitialRootHeight = avgRootAndRate[0]; double avgInitialRate = avgRootAndRate[1]; // double growthRateMaximum = 1E6; double birthRateMaximum = 1E6; // double substitutionRateMaximum = 100; // double logStdevMaximum = 10; // double substitutionParameterMaximum = 100; // if (options.clockModelOptions.getRateOptionClockModel() == FixRateType.FIX_MEAN // || options.clockModelOptions.getRateOptionClockModel() == FixRateType.RELATIVE_TO) { // // growthRateMaximum = 1E6 * avgInitialRate; birthRateMaximum = 1E6 * avgInitialRate; // } // if (options.clockModelOptions.getRateOptionClockModel() == FixRateType.FIX_MEAN) { // double rate = options.clockModelOptions.getMeanRelativeRate(); // // growthRateMaximum = 1E6 * rate; // birthRateMaximum = 1E6 * rate; // // if (options.hasData()) { // initialRootHeight = meanDistance / rate; // // initialRootHeight = round(initialRootHeight, 2); // } // // } else { // if (options.maximumTipHeight > 0) { // initialRootHeight = options.maximumTipHeight * 10.0; // } // // initialRate = round((meanDistance * 0.2) / initialRootHeight, 2); // } // double timeScaleMaximum = MathUtils.round(avgInitialRootHeight * 1000.0, 2); // if (!options.hasData()) param.setPriorEdited(false); if (!param.isPriorEdited()) { switch (param.scaleType) { case TIME_SCALE: // param.lower = Math.max(0.0, param.lower); // param.upper = Math.min(timeScaleMaximum, param.upper); // if (param.isNodeHeight) { //TODO only affecting "treeModel.rootHeight", need to review // param.lower = options.maximumTipHeight; //// param.upper = timeScaleMaximum; //// param.initial = avgInitialRootHeight; // if (param.getOptions() instanceof PartitionTreeModel) { // move to PartitionTreeModel // param.initial = ((PartitionTreeModel) param.getOptions()).getInitialRootHeight(); // } // } else { param.initial = avgInitialRootHeight; // } break; case LOG_TIME_SCALE: param.initial = Math.log(avgInitialRootHeight); break; case T50_SCALE: // param.lower = Math.max(0.0, param.lower); //param.upper = Math.min(timeScaleMaximum, param.upper); param.initial = avgInitialRootHeight / 5.0; break; case GROWTH_RATE_SCALE: param.initial = avgInitialRootHeight / 1000; // use Laplace if (param.getBaseName().startsWith("logistic")) { param.scale = Math.log(1000) / avgInitialRootHeight; // System.out.println("logistic"); } else { param.scale = Math.log(10000) / avgInitialRootHeight; // System.out.println("not logistic"); } break; case BIRTH_RATE_SCALE: // param.uniformLower = Math.max(0.0, param.lower); // param.uniformUpper = Math.min(birthRateMaximum, param.upper); param.initial = MathUtils.round(1 / options.treeModelOptions.getExpectedAvgBranchLength(avgInitialRootHeight), 2); break; case ORIGIN_SCALE: param.initial = MathUtils.round(avgInitialRootHeight * 1.1, 2); break; case SUBSTITUTION_RATE_SCALE: // param.lower = Math.max(0.0, param.lower); //param.upper = Math.min(substitutionRateMaximum, param.upper); param.initial = avgInitialRate; break; case LOG_STDEV_SCALE: // param.lower = Math.max(0.0, param.lower); //param.upper = Math.min(logStdevMaximum, param.upper); break; case SUBSTITUTION_PARAMETER_SCALE: // param.lower = Math.max(0.0, param.lower); //param.upper = Math.min(substitutionParameterMaximum, param.upper); break; // Now have a field 'isZeroOne' // case UNITY_SCALE: // param.lower = 0.0; // param.upper = 1.0; // break; case ROOT_RATE_SCALE: param.initial = avgInitialRate; param.shape = 0.5; param.scale = param.initial / 0.5; break; case LOG_VAR_SCALE: param.initial = avgInitialRate; param.shape = 2.0; param.scale = param.initial / 2.0; break; } } } public BeautiOptions getOptions() { return options; } }