package dr.app.beauti.generator; import dr.app.beauti.components.ComponentFactory; import dr.app.beauti.options.*; import dr.app.beauti.types.ClockType; import dr.app.beauti.types.FixRateType; import dr.app.beauti.types.RelativeRatesType; import dr.app.beauti.types.TreePriorType; import dr.app.beauti.util.XMLWriter; import dr.evomodel.operators.BitFlipInSubstitutionModelOperator; import dr.evomodel.substmodel.AbstractSubstitutionModel; import dr.evomodel.tree.TreeModel; import dr.evomodelxml.coalescent.GMRFSkyrideLikelihoodParser; import dr.evomodelxml.coalescent.VariableDemographicModelParser; import dr.evomodelxml.coalescent.operators.GMRFSkyrideBlockUpdateOperatorParser; import dr.evomodelxml.coalescent.operators.SampleNonActiveGibbsOperatorParser; import dr.evomodelxml.operators.*; import dr.evomodelxml.speciation.BirthDeathModelParser; import dr.evomodelxml.speciation.SpeciesTreeModelParser; import dr.evomodelxml.speciation.YuleModelParser; import dr.evomodelxml.substmodel.GeneralSubstitutionModelParser; import dr.inference.model.ParameterParser; import dr.inference.operators.RateBitExchangeOperator; import dr.inference.operators.SimpleOperatorSchedule; import dr.inferencexml.model.CompoundParameterParser; import dr.inferencexml.operators.*; import dr.util.Attribute; import dr.xml.XMLParser; import java.util.List; /** * @author Alexei Drummond * @author Andrew Rambaut * @author Walter Xie */ public class OperatorsGenerator extends Generator { public OperatorsGenerator(BeautiOptions options, ComponentFactory[] components) { super(options, components); } /** * Write the operator schedule XML block. * * @param operators the list of operators * @param writer the writer */ public void writeOperatorSchedule(List<Operator> operators, XMLWriter writer) { Attribute[] operatorAttributes; // switch (options.coolingSchedule) { // case SimpleOperatorSchedule.LOG_SCHEDULE: // if (options.nodeHeightPrior == TreePriorType.GMRF_SKYRIDE) { // TODO: multi-prior, currently simplify to share same prior case if (options.isShareSameTreePrior() && options.getPartitionTreePriors().get(0).getNodeHeightPrior() == TreePriorType.GMRF_SKYRIDE) { operatorAttributes = new Attribute[2]; operatorAttributes[1] = new Attribute.Default<String>(SimpleOperatorScheduleParser.OPTIMIZATION_SCHEDULE, SimpleOperatorSchedule.LOG_STRING); } else { // break; // default: operatorAttributes = new Attribute[1]; } operatorAttributes[0] = new Attribute.Default<String>(XMLParser.ID, "operators"); writer.writeComment("Define operators"); writer.writeOpenTag( SimpleOperatorScheduleParser.OPERATOR_SCHEDULE, operatorAttributes // new Attribute[]{new Attribute.Default<String>(XMLParser.ID, "operators")} ); for (Operator operator : operators) { if (operator.weight > 0. && operator.inUse) { setModelPrefix(operator.getPrefix()); writeOperator(operator, writer); } } generateInsertionPoint(ComponentGenerator.InsertionPoint.IN_OPERATORS, writer); // Added for special operators writer.writeCloseTag(SimpleOperatorScheduleParser.OPERATOR_SCHEDULE); } private void writeOperator(Operator operator, XMLWriter writer) { switch (operator.operatorType) { case SCALE: writeScaleOperator(operator, writer); break; case RANDOM_WALK: writeRandomWalkOperator(operator, writer); break; case RANDOM_WALK_ABSORBING: writeRandomWalkOperator(operator, false, writer); break; case RANDOM_WALK_INT: writeRandomWalkIntegerOperator(operator, writer); break; case RANDOM_WALK_REFLECTING: writeRandomWalkOperator(operator, true, writer); break; case INTEGER_RANDOM_WALK: writeIntegerRandomWalkOperator(operator, writer); break; case UP_DOWN: writeUpDownOperator(UpDownOperatorParser.UP_DOWN_OPERATOR, operator, writer); break; case MICROSAT_UP_DOWN: writeUpDownOperator(MicrosatUpDownOperatorParser.MICROSAT_UP_DOWN_OPERATOR, operator, writer); break; case UP_DOWN_ALL_RATES_HEIGHTS: writeUpDownOperatorAllRatesTrees(operator, writer); break; case SCALE_ALL: writeScaleAllOperator(operator, writer); break; case SCALE_INDEPENDENTLY: writeScaleOperator(operator, writer, true); break; case CENTERED_SCALE: writeCenteredOperator(operator, writer); break; case DELTA_EXCHANGE: writeDeltaOperator(operator, writer); break; case INTEGER_DELTA_EXCHANGE: writeIntegerDeltaOperator(operator, writer); break; case SWAP: writeSwapOperator(operator, writer); break; case BITFLIP: writeBitFlipOperator(operator, writer); break; case BITFIP_IN_SUBST: writeBitFlipInSubstOperator(operator, writer); break; case RATE_BIT_EXCHANGE: writeRateBitExchangeOperator(operator, writer); break; case TREE_BIT_MOVE: writeTreeBitMoveOperator(operator, writer); break; case UNIFORM: writeUniformOperator(operator, writer); break; case INTEGER_UNIFORM: writeIntegerUniformOperator(operator, writer); break; case SUBTREE_SLIDE: writeSubtreeSlideOperator(operator, writer); break; case NARROW_EXCHANGE: writeNarrowExchangeOperator(operator, writer); break; case WIDE_EXCHANGE: writeWideExchangeOperator(operator, writer); break; case WILSON_BALDING: writeWilsonBaldingOperator(operator, writer); break; case SAMPLE_NONACTIVE: writeSampleNonActiveOperator(operator, writer); break; case SCALE_WITH_INDICATORS: writeScaleWithIndicatorsOperator(operator, writer); break; case GMRF_GIBBS_OPERATOR: writeGMRFGibbsOperator(operator, writer); break; case NODE_REHIGHT: writeSpeciesTreeOperator(operator, writer); break; default: throw new IllegalArgumentException("Unknown operator type"); } } private void writeParameter1Ref(XMLWriter writer, Operator operator) { writer.writeIDref(ParameterParser.PARAMETER, operator.parameter1.getName()); } private void writeParameter2Ref(XMLWriter writer, Operator operator) { writer.writeIDref(ParameterParser.PARAMETER, operator.parameter2.getName()); } private void writeOperatorRef(XMLWriter writer, Operator operator) { writer.writeIDref(ParameterParser.PARAMETER, operator.getName()); } private void writeScaleOperator(Operator operator, XMLWriter writer) { writer.writeOpenTag( ScaleOperatorParser.SCALE_OPERATOR, new Attribute[]{ new Attribute.Default<Double>(ScaleOperatorParser.SCALE_FACTOR, operator.tuning), getWeightAttribute(operator.weight) }); writeParameter1Ref(writer, operator); // writeOperatorRef(writer, operator); writer.writeCloseTag(ScaleOperatorParser.SCALE_OPERATOR); } private void writeScaleOperator(Operator operator, XMLWriter writer, boolean indepedently) { writer.writeOpenTag( ScaleOperatorParser.SCALE_OPERATOR, new Attribute[]{ new Attribute.Default<Double>(ScaleOperatorParser.SCALE_FACTOR, operator.tuning), getWeightAttribute(operator.weight), new Attribute.Default<String>(ScaleOperatorParser.SCALE_ALL_IND, indepedently ? "true" : "false") }); writeParameter1Ref(writer, operator); // writeOperatorRef(writer, operator); writer.writeCloseTag(ScaleOperatorParser.SCALE_OPERATOR); } private void writeRandomWalkOperator(Operator operator, XMLWriter writer) { final String name = RandomWalkOperatorParser.RANDOM_WALK_OPERATOR; writer.writeOpenTag( name, new Attribute[]{ new Attribute.Default<Double>("windowSize", operator.tuning), getWeightAttribute(operator.weight) }); writeParameter1Ref(writer, operator); // writeOperatorRef(writer, operator); writer.writeCloseTag(name); } private void writeRandomWalkOperator(Operator operator, boolean reflecting, XMLWriter writer) { final String name = RandomWalkOperatorParser.RANDOM_WALK_OPERATOR; writer.writeOpenTag( name, new Attribute[]{ new Attribute.Default<Double>("windowSize", operator.tuning), getWeightAttribute(operator.weight), new Attribute.Default<String>("boundaryCondition", (reflecting ? "reflecting" : "absorbing")) }); writeParameter1Ref(writer, operator); // writeOperatorRef(writer, operator); writer.writeCloseTag(name); } private void writeRandomWalkIntegerOperator(Operator operator, XMLWriter writer) { final String name = RandomWalkIntegerOperatorParser.RANDOM_WALK_INTEGER_OPERATOR; writer.writeOpenTag( name, new Attribute[]{ new Attribute.Default<Double>("windowSize", operator.tuning), getWeightAttribute(operator.weight) }); writeParameter1Ref(writer, operator); writer.writeCloseTag(name); } private void writeIntegerRandomWalkOperator(Operator operator, XMLWriter writer) { int windowSize = (int) Math.round(operator.tuning); if (windowSize < 1) windowSize = 1; final String name = RandomWalkIntegerOperatorParser.RANDOM_WALK_INTEGER_OPERATOR; writer.writeOpenTag( name, new Attribute[]{ new Attribute.Default<Integer>("windowSize", windowSize), getWeightAttribute(operator.weight) }); writeParameter1Ref(writer, operator); // writeOperatorRef(writer, operator); writer.writeCloseTag(name); } private void writeScaleAllOperator(Operator operator, XMLWriter writer) { writer.writeOpenTag( ScaleOperatorParser.SCALE_OPERATOR, new Attribute[]{ new Attribute.Default<Double>(ScaleOperatorParser.SCALE_FACTOR, operator.tuning), new Attribute.Default<String>(ScaleOperatorParser.SCALE_ALL, "true"), getWeightAttribute(operator.weight) }); if (operator.parameter2 == null) { writeParameter1Ref(writer, operator); } else { writer.writeOpenTag(CompoundParameterParser.COMPOUND_PARAMETER); writeParameter1Ref(writer, operator); // writer.writeIDref(ParameterParser.PARAMETER, operator.parameter2.getName()); writeParameter2Ref(writer, operator); writer.writeCloseTag(CompoundParameterParser.COMPOUND_PARAMETER); } writer.writeCloseTag(ScaleOperatorParser.SCALE_OPERATOR); } private void writeCenteredOperator(Operator operator, XMLWriter writer) { writer.writeOpenTag(CenteredScaleOperatorParser.CENTERED_SCALE, new Attribute[]{ new Attribute.Default<Double>(CenteredScaleOperatorParser.SCALE_FACTOR, operator.tuning), getWeightAttribute(operator.weight) } ); writeParameter1Ref(writer, operator); // writeOperatorRef(writer, operator); writer.writeCloseTag(CenteredScaleOperatorParser.CENTERED_SCALE); } private void writeDeltaOperator(Operator operator, XMLWriter writer) { if (operator.getBaseName().startsWith(RelativeRatesType.MU_RELATIVE_RATES.toString())) { int[] parameterWeights = ((PartitionSubstitutionModel) operator.parameter1.getOptions()).getPartitionCodonWeights(); if (parameterWeights != null && parameterWeights.length > 1) { String pw = "" + parameterWeights[0]; for (int i = 1; i < parameterWeights.length; i++) { pw += " " + parameterWeights[i]; } writer.writeOpenTag(DeltaExchangeOperatorParser.DELTA_EXCHANGE, new Attribute[]{ new Attribute.Default<Double>(DeltaExchangeOperatorParser.DELTA, operator.tuning), new Attribute.Default<String>(DeltaExchangeOperatorParser.PARAMETER_WEIGHTS, pw), getWeightAttribute(operator.weight) } ); } } else if (operator.getBaseName().startsWith(RelativeRatesType.CLOCK_RELATIVE_RATES.toString())) { int[] parameterWeights = options.clockModelOptions.getPartitionClockWeights(operator.getClockModelGroup()); if (parameterWeights != null && parameterWeights.length > 1) { String pw = "" + parameterWeights[0]; for (int i = 1; i < parameterWeights.length; i++) { pw += " " + parameterWeights[i]; } writer.writeOpenTag(DeltaExchangeOperatorParser.DELTA_EXCHANGE, new Attribute[]{ new Attribute.Default<Double>(DeltaExchangeOperatorParser.DELTA, operator.tuning), new Attribute.Default<String>(DeltaExchangeOperatorParser.PARAMETER_WEIGHTS, pw), getWeightAttribute(operator.weight) } ); } } else { writer.writeOpenTag(DeltaExchangeOperatorParser.DELTA_EXCHANGE, new Attribute[]{ new Attribute.Default<Double>(DeltaExchangeOperatorParser.DELTA, operator.tuning), getWeightAttribute(operator.weight) } ); } writeParameter1Ref(writer, operator); writer.writeCloseTag(DeltaExchangeOperatorParser.DELTA_EXCHANGE); } private void writeIntegerDeltaOperator(Operator operator, XMLWriter writer) { writer.writeOpenTag(DeltaExchangeOperatorParser.DELTA_EXCHANGE, new Attribute[]{ new Attribute.Default<String>(DeltaExchangeOperatorParser.DELTA, Integer.toString((int) operator.tuning)), new Attribute.Default<String>("integer", "true"), getWeightAttribute(operator.weight), new Attribute.Default<String>("autoOptimize", "false") } ); writeParameter1Ref(writer, operator); // writeOperatorRef(writer, operator); writer.writeCloseTag(DeltaExchangeOperatorParser.DELTA_EXCHANGE); } private void writeSwapOperator(Operator operator, XMLWriter writer) { writer.writeOpenTag(SwapOperatorParser.SWAP_OPERATOR, new Attribute[]{ new Attribute.Default<String>("size", Integer.toString((int) operator.tuning)), getWeightAttribute(operator.weight), new Attribute.Default<String>("autoOptimize", "false") } ); writeParameter1Ref(writer, operator); // writeOperatorRef(writer, operator); writer.writeCloseTag(SwapOperatorParser.SWAP_OPERATOR); } private void writeBitFlipOperator(Operator operator, XMLWriter writer) { writer.writeOpenTag(BitFlipOperatorParser.BIT_FLIP_OPERATOR, getWeightAttribute(operator.weight)); writeParameter1Ref(writer, operator); // writeOperatorRef(writer, operator); writer.writeCloseTag(BitFlipOperatorParser.BIT_FLIP_OPERATOR); } private void writeBitFlipInSubstOperator(Operator operator, XMLWriter writer) { writer.writeOpenTag(BitFlipInSubstitutionModelOperator.BIT_FLIP_OPERATOR, new Attribute[]{ new Attribute.Default<Double>(ScaleOperatorParser.SCALE_FACTOR, operator.tuning), getWeightAttribute(operator.weight)}); writeParameter1Ref(writer, operator); // writeOperatorRef(writer, operator); PartitionSubstitutionModel model = (PartitionSubstitutionModel) operator.getOptions(); writer.writeIDref(GeneralSubstitutionModelParser.GENERAL_SUBSTITUTION_MODEL, model.getPrefix() + AbstractSubstitutionModel.MODEL); // <svsGeneralSubstitutionModel idref="originModel"/> writer.writeCloseTag(BitFlipInSubstitutionModelOperator.BIT_FLIP_OPERATOR); } private void writeRateBitExchangeOperator(Operator operator, XMLWriter writer) { writer.writeOpenTag(RateBitExchangeOperator.OPERATOR_NAME, getWeightAttribute(operator.weight)); writer.writeOpenTag(RateBitExchangeOperator.BITS); writeParameter1Ref(writer, operator); writer.writeCloseTag(RateBitExchangeOperator.BITS); writer.writeOpenTag(RateBitExchangeOperator.RATES); writeParameter2Ref(writer, operator); writer.writeCloseTag(RateBitExchangeOperator.RATES); writer.writeCloseTag(RateBitExchangeOperator.OPERATOR_NAME); } private void writeTreeBitMoveOperator(Operator operator, XMLWriter writer) { writer.writeOpenTag(TreeBitMoveOperatorParser.BIT_MOVE_OPERATOR, getWeightAttribute(operator.weight)); writer.writeIDref(TreeModel.TREE_MODEL, modelPrefix + TreeModel.TREE_MODEL); writer.writeCloseTag(TreeBitMoveOperatorParser.BIT_MOVE_OPERATOR); } private void writeUniformOperator(Operator operator, XMLWriter writer) { writer.writeOpenTag("uniformOperator", getWeightAttribute(operator.weight)); writeParameter1Ref(writer, operator); // writeOperatorRef(writer, operator); writer.writeCloseTag("uniformOperator"); } private void writeIntegerUniformOperator(Operator operator, XMLWriter writer) { writer.writeOpenTag(UniformIntegerOperatorParser.UNIFORM_INTEGER_OPERATOR, getWeightAttribute(operator.weight)); writeParameter1Ref(writer, operator); // writeOperatorRef(writer, operator); writer.writeCloseTag(UniformIntegerOperatorParser.UNIFORM_INTEGER_OPERATOR); } private void writeNarrowExchangeOperator(Operator operator, XMLWriter writer) { writer.writeOpenTag(ExchangeOperatorParser.NARROW_EXCHANGE, getWeightAttribute(operator.weight)); writer.writeIDref(TreeModel.TREE_MODEL, modelPrefix + TreeModel.TREE_MODEL); writer.writeCloseTag(ExchangeOperatorParser.NARROW_EXCHANGE); } private void writeWideExchangeOperator(Operator operator, XMLWriter writer) { writer.writeOpenTag(ExchangeOperatorParser.WIDE_EXCHANGE, getWeightAttribute(operator.weight)); writer.writeIDref(TreeModel.TREE_MODEL, modelPrefix + TreeModel.TREE_MODEL); writer.writeCloseTag(ExchangeOperatorParser.WIDE_EXCHANGE); } private void writeWilsonBaldingOperator(Operator operator, XMLWriter writer) { writer.writeOpenTag(WilsonBaldingParser.WILSON_BALDING, getWeightAttribute(operator.weight)); writer.writeIDref(TreeModel.TREE_MODEL, modelPrefix + TreeModel.TREE_MODEL); // not supported anymore. probably never worked. (todo) get it out of GUI too // if (options.nodeHeightPrior == TreePriorType.CONSTANT) { // treePriorGenerator.writeNodeHeightPriorModelRef(writer); // } writer.writeCloseTag(WilsonBaldingParser.WILSON_BALDING); } private void writeSampleNonActiveOperator(Operator operator, XMLWriter writer) { writer.writeOpenTag(SampleNonActiveGibbsOperatorParser.SAMPLE_NONACTIVE_GIBBS_OPERATOR, getWeightAttribute(operator.weight)); writer.writeOpenTag(SampleNonActiveGibbsOperatorParser.DISTRIBUTION); writeOperatorRef(writer, operator); writer.writeCloseTag(SampleNonActiveGibbsOperatorParser.DISTRIBUTION); writer.writeOpenTag(SampleNonActiveGibbsOperatorParser.DATA_PARAMETER); writeParameter1Ref(writer, operator); writer.writeCloseTag(SampleNonActiveGibbsOperatorParser.DATA_PARAMETER); writer.writeOpenTag(SampleNonActiveGibbsOperatorParser.INDICATOR_PARAMETER); writeParameter2Ref(writer, operator); writer.writeCloseTag(SampleNonActiveGibbsOperatorParser.INDICATOR_PARAMETER); writer.writeCloseTag(SampleNonActiveGibbsOperatorParser.SAMPLE_NONACTIVE_GIBBS_OPERATOR); } private void writeGMRFGibbsOperator(Operator operator, XMLWriter writer) { writer.writeOpenTag( GMRFSkyrideBlockUpdateOperatorParser.BLOCK_UPDATE_OPERATOR, new Attribute[]{ new Attribute.Default<Double>(GMRFSkyrideBlockUpdateOperatorParser.SCALE_FACTOR, operator.tuning), getWeightAttribute(operator.weight) } ); writer.writeIDref(GMRFSkyrideLikelihoodParser.SKYLINE_LIKELIHOOD, modelPrefix + "skyride"); writer.writeCloseTag(GMRFSkyrideBlockUpdateOperatorParser.BLOCK_UPDATE_OPERATOR); } private void writeScaleWithIndicatorsOperator(Operator operator, XMLWriter writer) { writer.writeOpenTag( ScaleOperatorParser.SCALE_OPERATOR, new Attribute[]{ new Attribute.Default<Double>(ScaleOperatorParser.SCALE_FACTOR, operator.tuning), getWeightAttribute(operator.weight) }); writeParameter1Ref(writer, operator); writer.writeOpenTag(ScaleOperatorParser.INDICATORS, new Attribute.Default<String>(ScaleOperatorParser.PICKONEPROB, "1.0")); writeParameter2Ref(writer, operator); writer.writeCloseTag(ScaleOperatorParser.INDICATORS); writer.writeCloseTag(ScaleOperatorParser.SCALE_OPERATOR); } private void writeSubtreeSlideOperator(Operator operator, XMLWriter writer) { writer.writeOpenTag(SubtreeSlideOperatorParser.SUBTREE_SLIDE, new Attribute[]{ new Attribute.Default<Double>("size", operator.tuning), new Attribute.Default<String>("gaussian", "true"), getWeightAttribute(operator.weight) } ); writer.writeIDref(TreeModel.TREE_MODEL, modelPrefix + TreeModel.TREE_MODEL); writer.writeCloseTag(SubtreeSlideOperatorParser.SUBTREE_SLIDE); } private void writeSpeciesTreeOperator(Operator operator, XMLWriter writer) { writer.writeOpenTag(TreeNodeSlideParser.TREE_NODE_REHEIGHT, new Attribute[]{ getWeightAttribute(operator.weight) } ); writer.writeIDref(TraitData.TRAIT_SPECIES, TraitData.TRAIT_SPECIES); writer.writeIDref(SpeciesTreeModelParser.SPECIES_TREE, Generator.SP_TREE); writer.writeCloseTag(TreeNodeSlideParser.TREE_NODE_REHEIGHT); } private void writeUpDownOperator(String opTag, Operator operator, XMLWriter writer) { writer.writeOpenTag(opTag, new Attribute[]{ new Attribute.Default<Double>(ScaleOperatorParser.SCALE_FACTOR, operator.tuning), getWeightAttribute(operator.weight) } ); writer.writeOpenTag(UpDownOperatorParser.UP); // for isEstimatedRate() = false, write nothing on up part of upDownOp if (!operator.parameter1.isFixed && operator.getClockModelGroup().getRateTypeOption() != FixRateType.FIX_MEAN) { writeParameter1Ref(writer, operator); } writer.writeCloseTag(UpDownOperatorParser.UP); writer.writeOpenTag(UpDownOperatorParser.DOWN); if (operator.tag == null) { // writer.writeIDref(ParameterParser.PARAMETER, operator.parameter2.getName()); writeParameter2Ref(writer, operator); } else { writer.writeIDref(operator.tag, operator.idref); } writer.writeCloseTag(UpDownOperatorParser.DOWN); writer.writeCloseTag(opTag); } private void writeUpDownOperatorAllRatesTrees(Operator operator, XMLWriter writer) { writer.writeOpenTag(UpDownOperatorParser.UP_DOWN_OPERATOR, new Attribute[]{ new Attribute.Default<Double>(ScaleOperatorParser.SCALE_FACTOR, operator.tuning), getWeightAttribute(operator.weight) } ); writer.writeOpenTag(UpDownOperatorParser.UP); for (PartitionClockModel model : options.getPartitionClockModels()) { if (model.isEstimatedRate()) { switch (model.getClockType()) { case STRICT_CLOCK: case RANDOM_LOCAL_CLOCK: writer.writeIDref(ParameterParser.PARAMETER, model.getPrefix() + "clock.rate"); break; case UNCORRELATED: switch (model.getClockDistributionType()) { case LOGNORMAL: writer.writeIDref(ParameterParser.PARAMETER, model.getPrefix() + ClockType.UCLD_MEAN); break; case GAMMA: throw new UnsupportedOperationException("Uncorrelated gamma relaxed clock model not implemented yet"); // break; case CAUCHY: throw new UnsupportedOperationException("Uncorrelated Cauchy relaxed clock model not implemented yet"); // break; case EXPONENTIAL: writer.writeIDref(ParameterParser.PARAMETER, model.getPrefix() + ClockType.UCED_MEAN); break; } break; case AUTOCORRELATED: throw new UnsupportedOperationException("Autocorrelated relaxed clock model not implemented yet"); // break; default: throw new IllegalArgumentException("Unknown clock model"); } } } if (options.useStarBEAST) { if (options.getPartitionTreePriors().get(0).getNodeHeightPrior() == TreePriorType.SPECIES_BIRTH_DEATH) { writer.writeIDref(ParameterParser.PARAMETER, TraitData.TRAIT_SPECIES + "." + BirthDeathModelParser.MEAN_GROWTH_RATE_PARAM_NAME); } else if (options.getPartitionTreePriors().get(0).getNodeHeightPrior() == TreePriorType.SPECIES_YULE) { writer.writeIDref(ParameterParser.PARAMETER, TraitData.TRAIT_SPECIES + "." + YuleModelParser.YULE + "." + YuleModelParser.BIRTH_RATE); } }// nothing for EBSP writer.writeCloseTag(UpDownOperatorParser.UP); writer.writeOpenTag(UpDownOperatorParser.DOWN); if (options.useStarBEAST) { writer.writeIDref(SpeciesTreeModelParser.SPECIES_TREE, SP_TREE); // <speciesTree idref="sptree" /> has to be the 1st always writer.writeIDref(ParameterParser.PARAMETER, TraitData.TRAIT_SPECIES + "." + options.starBEASTOptions.POP_MEAN); writer.writeIDref(ParameterParser.PARAMETER, SpeciesTreeModelParser.SPECIES_TREE + "." + SPLIT_POPS); } else if (options.isEBSPSharingSamePrior()) { writer.writeIDref(ParameterParser.PARAMETER, VariableDemographicModelParser.demoElementName + ".populationMean"); writer.writeIDref(ParameterParser.PARAMETER, VariableDemographicModelParser.demoElementName + ".popSize"); } for (PartitionTreeModel tree : options.getPartitionTreeModels()) { writer.writeIDref(ParameterParser.PARAMETER, tree.getPrefix() + "treeModel.allInternalNodeHeights"); } writer.writeCloseTag(UpDownOperatorParser.DOWN); writer.writeCloseTag(UpDownOperatorParser.UP_DOWN_OPERATOR); } private Attribute getWeightAttribute(double weight) { if (weight == (int)weight) { return new Attribute.Default<Integer>("weight", (int)weight); } else { return new Attribute.Default<Double>("weight", weight); } } }