From 97a7741ca6dcd7de09ad3d6342928174babb12e7 Mon Sep 17 00:00:00 2001 From: xuyuan Date: Mon, 13 May 2024 15:18:12 +1200 Subject: [PATCH] Use beast ExponentialGrowth, use GenericTreeLikelihood for lphybeast unphase method, and Gompertz parameter changes #55 #57 --- .../populationmodel/GompertzGrowth.java | 247 +++++++++--------- .../populationmodel/PopFuncWithUpDownOp.java | 20 +- .../examples/gompertzCoalescent.lphy | 19 +- phylonco-lphy/examples/gompertzGT16.lphy | 22 ++ .../tobeast/generators/GTUnphaseToBEAST.java | 45 ++-- .../generators/PopFuncCoalescentToBEAST.java | 11 +- .../tobeast/values/ExponentialToBEAST.java | 4 +- .../tobeast/values/GompertzToBEAST.java | 5 +- 8 files changed, 200 insertions(+), 173 deletions(-) create mode 100644 phylonco-lphy/examples/gompertzGT16.lphy diff --git a/phylonco-beast/src/main/java/phylonco/beast/evolution/populationmodel/GompertzGrowth.java b/phylonco-beast/src/main/java/phylonco/beast/evolution/populationmodel/GompertzGrowth.java index 1a0a54d..453767f 100644 --- a/phylonco-beast/src/main/java/phylonco/beast/evolution/populationmodel/GompertzGrowth.java +++ b/phylonco-beast/src/main/java/phylonco/beast/evolution/populationmodel/GompertzGrowth.java @@ -1,7 +1,9 @@ package phylonco.beast.evolution.populationmodel; import beast.base.core.*; +import beast.base.evolution.tree.Tree; import beast.base.evolution.tree.coalescent.PopulationFunction; +import beast.base.inference.operator.UpDownOperator; import beast.base.inference.parameter.RealParameter; import org.apache.commons.math3.analysis.UnivariateFunction; import org.apache.commons.math3.analysis.integration.IterativeLegendreGaussIntegrator; @@ -12,160 +14,153 @@ import java.util.List; - @Description("Coalescent intervals for a gompertz growing population.") - public class GompertzGrowth extends PopulationFunction.Abstract implements Loggable { -// final public Input f0Input = new Input<>("f0", -// "Initial proportion of the carrying capacity.", Input.Validate.REQUIRED); - - final public Input N0Input = new Input<>("N0", - "Initial pop", Input.Validate.REQUIRED); - - final public Input bInput = new Input<>("b", - "Initial growth rate of tumor growth. Should be greater than 0.", Input.Validate.REQUIRED); - final public Input NInfinityInput = new Input<>("NInfinity", - "Carrying capacity of the population.", Input.Validate.REQUIRED); +@Description("Coalescent intervals for a gompertz growing population.") +public class GompertzGrowth extends PopulationFunction.Abstract implements Loggable, PopFuncWithUpDownOp { + final public Input f0Input = new Input<>("f0", + "Initial proportion of the carrying capacity.", Input.Validate.REQUIRED); + final public Input bInput = new Input<>("b", + "Initial growth rate of tumor growth. Should be greater than 0.", Input.Validate.REQUIRED); +// final public Input NInfinityInput = new Input<>("NInfinity", +// "Carrying capacity of the population.", Input.Validate.REQUIRED); + final public Input N0Input = new Input<>("N0", + "Initial population size.", Input.Validate.REQUIRED); + + public GompertzGrowth() { + // Example of setting up inputs with default values + // f0Input.setValue(new RealParameter("0.5"), this); + // bInput.setValue(new RealParameter("0.1"), this); + // NInfinityInput.setValue(new RealParameter("1000"), this); + } - public GompertzGrowth() { - // Example of setting up inputs with default values -// f0Input.setValue(new RealParameter("0.5"), this); -// bInput.setValue(new RealParameter("0.1"), this); -// NInfinityInput.setValue(new RealParameter("1000"), this); + @Override + public void initAndValidate() { + if (f0Input.get() != null && f0Input.get() instanceof RealParameter) { + RealParameter f0Param = (RealParameter) f0Input.get(); + f0Param.setBounds(Math.max(0.0, f0Param.getLower()), f0Param.getUpper()); } - @Override - public void initAndValidate() { -// if (f0Input.get() != null && f0Input.get() instanceof RealParameter) { -// RealParameter f0Param = (RealParameter) f0Input.get(); -// f0Param.setBounds(Math.max(0.0, f0Param.getLower()), f0Param.getUpper()); -// } - - if (N0Input.get() != null && N0Input.get() instanceof RealParameter) { - RealParameter N0Param = (RealParameter) N0Input.get(); - N0Param.setBounds(Math.max(0.0, N0Param.getLower()), N0Param.getUpper()); - } - - if (bInput.get() != null && bInput.get() instanceof RealParameter) { - RealParameter bParam = (RealParameter) bInput.get(); - bParam.setBounds(0.0, Double.POSITIVE_INFINITY); // b should be positive for Gompertz growth - } - - if (NInfinityInput.get() != null && NInfinityInput.get() instanceof RealParameter) { - RealParameter NInfinityParam = (RealParameter) NInfinityInput.get(); - NInfinityParam.setBounds(Math.max(0.0, NInfinityParam.getLower()), NInfinityParam.getUpper()); - } - - // Compute N0 from f0 and NInfinity if they are not null and are RealParameters -// if (f0Input.get() != null && NInfinityInput.get() != null && -// f0Input.get() instanceof RealParameter && NInfinityInput.get() instanceof RealParameter) { -// double f0 = ((RealParameter) f0Input.get()).getValue(); -// double NInfinity = ((RealParameter) NInfinityInput.get()).getValue(); - + if (bInput.get() != null && bInput.get() instanceof RealParameter) { + RealParameter bParam = (RealParameter) bInput.get(); + bParam.setBounds(0.0, Double.POSITIVE_INFINITY); // b should be positive for Gompertz growth + } +// if (NInfinityInput.get() != null && NInfinityInput.get() instanceof RealParameter) { +// RealParameter NInfinityParam = (RealParameter) NInfinityInput.get(); +// NInfinityParam.setBounds(Math.max(0.0, NInfinityParam.getLower()), NInfinityParam.getUpper()); +// } + if (N0Input.get() != null && N0Input.get() instanceof RealParameter) { + RealParameter N0Param = (RealParameter) N0Input.get(); + N0Param.setBounds(Math.max(0.0, N0Param.getLower()), N0Param.getUpper()); } -// public double getN0() { -// return getNInfinity() * getF0(); + // Compute N0 from f0 and NInfinity if they are not null and are RealParameters +// if (f0Input.get() != null && NInfinityInput.get() != null && +// f0Input.get() instanceof RealParameter && NInfinityInput.get() instanceof RealParameter) { +// double f0 = ((RealParameter) f0Input.get()).getValue(); +// double NInfinity = ((RealParameter) NInfinityInput.get()).getValue(); // } + } -// public double getF0() { -// return f0Input.get().getArrayValue(); -// } + public double getNInfinity() { + return getN0() / getF0(); + } - public double getN0() { - return N0Input.get().getArrayValue(); - } + public double getF0() { + return f0Input.get().getArrayValue(); + } - public final double getGrowthRateB() { - return bInput.get().getArrayValue(); - } + public final double getGrowthRateB() { + return bInput.get().getArrayValue(); + } - public double getNInfinity() { - return NInfinityInput.get().getArrayValue(); - } +// public double getNInfinity() { +// return NInfinityInput.get().getArrayValue(); +// } + public double getN0() { + return N0Input.get().getArrayValue(); + } - @Override - public List getParameterIds() { - List ids = new ArrayList<>(); - // add f0 and b parameter ids - if (NInfinityInput.get() instanceof BEASTInterface) - ids.add(((BEASTInterface)NInfinityInput.get()).getID()); - return ids; - } + @Override + public List getParameterIds() { + List ids = new ArrayList<>(); + // add f0 and b parameter ids + if (N0Input.get() instanceof BEASTInterface) + ids.add(((BEASTInterface)N0Input.get()).getID()); + return ids; + } - @Override - public double getPopSize(double t) { -// double f0 = getF0(); - double b = getGrowthRateB(); - double NInfinity = getNInfinity(); - double N0 = getN0(); + @Override + public double getPopSize(double t) { + double f0 = getF0(); + double b = getGrowthRateB(); + double NInfinity = getNInfinity(); + double N0 = getN0(); - double popSize = N0 * Math.exp(Math.log(NInfinity / N0) * (1 - Math.exp(b * t))); + double popSize = N0 * Math.exp(Math.log(NInfinity / N0) * (1 - Math.exp(b * t))); - return popSize; - } + return popSize; + } - @Override - public double getIntensity(double t) { - if (t == 0) return 0; - UnivariateFunction function = time -> { - double popSize = getPopSize(time); - return 1 / Math.max(popSize, 1e-20); - }; - IterativeLegendreGaussIntegrator integrator = new IterativeLegendreGaussIntegrator(5, 1.0e-12, 1.0e-8, 2, 10000); - // default intensity if fails - double intensity = 0; - try { - int maxEval = 100000; // trying maxEval = 100000 to test speed - // previous maxEval default = Integer.MAX_VALUE; - intensity = integrator.integrate(maxEval, function, 0, t); - } catch (TooManyEvaluationsException ex) { - // System.err.println("f0 = " + getF0() + ", b=" + getGrowthRateB() + " NInfinity=" + getNInfinity()); - return intensity; - } + @Override + public double getIntensity(double t) { + if (t == 0) return 0; + UnivariateFunction function = time -> { + double popSize = getPopSize(time); + return 1 / Math.max(popSize, 1e-20); + }; + IterativeLegendreGaussIntegrator integrator = new IterativeLegendreGaussIntegrator(5, 1.0e-12, 1.0e-8, 2, 10000); + // default intensity if fails + double intensity = 0; + try { + int maxEval = 100000; // trying maxEval = 100000 to test speed + // previous maxEval default = Integer.MAX_VALUE; + intensity = integrator.integrate(maxEval, function, 0, t); + } catch (TooManyEvaluationsException ex) { + // System.err.println("f0 = " + getF0() + ", b=" + getGrowthRateB() + " NInfinity=" + getNInfinity()); return intensity; } + return intensity; + } - @Override - public double getInverseIntensity(double x) { - return 0; - } - - @Override - public void init(PrintStream printStream) { + @Override + public double getInverseIntensity(double x) { + return 0; + } - } + @Override + public void init(PrintStream printStream) { - @Override - public void log(long step, PrintStream printStream) { - } + } - @Override - public void close(PrintStream printStream) { + @Override + public void log(long step, PrintStream printStream) { + } - } + @Override + public void close(PrintStream printStream) { -// @Override -// public UpDownOperator getUpDownOperator(Tree tree) { -// -// UpDownOperator upDownOperator = new UpDownOperator(); -// -// String idStr = getID() + "Up" + tree.getID() + "DownOperator"; -// upDownOperator.setID(idStr); -// -// upDownOperator.setInputValue("scaleFactor", 0.75); -// upDownOperator.setInputValue("weight", 3.0); -// -// upDownOperator.setInputValue("up", this.f0Input.get()); -// upDownOperator.setInputValue("up", this.bInput.get()); -// upDownOperator.setInputValue("down", tree); -// upDownOperator.initAndValidate(); -// return upDownOperator; -// -// } } + @Override + public UpDownOperator getUpDownOperator(Tree tree) { + + UpDownOperator upDownOperator = new UpDownOperator(); + String idStr = getID() + "Up" + tree.getID() + "DownOperator"; + upDownOperator.setID(idStr); + + upDownOperator.setInputValue("scaleFactor", 0.75); + upDownOperator.setInputValue("weight", 3.0); + + upDownOperator.setInputValue("up", this.f0Input.get()); + upDownOperator.setInputValue("up", this.bInput.get()); + upDownOperator.setInputValue("down", tree); + upDownOperator.initAndValidate(); + return upDownOperator; + + } +} \ No newline at end of file diff --git a/phylonco-beast/src/main/java/phylonco/beast/evolution/populationmodel/PopFuncWithUpDownOp.java b/phylonco-beast/src/main/java/phylonco/beast/evolution/populationmodel/PopFuncWithUpDownOp.java index 8422bc0..1f0a46f 100644 --- a/phylonco-beast/src/main/java/phylonco/beast/evolution/populationmodel/PopFuncWithUpDownOp.java +++ b/phylonco-beast/src/main/java/phylonco/beast/evolution/populationmodel/PopFuncWithUpDownOp.java @@ -1,10 +1,10 @@ -//package phylonco.beast.evolution.populationmodel; -// -// -//import beast.base.evolution.tree.Tree; -//import beast.base.inference.operator.UpDownOperator; -// -//public interface PopFuncWithUpDownOp { -// -// UpDownOperator getUpDownOperator(Tree tree); -//} +package phylonco.beast.evolution.populationmodel; + + +import beast.base.evolution.tree.Tree; +import beast.base.inference.operator.UpDownOperator; + +public interface PopFuncWithUpDownOp { + + UpDownOperator getUpDownOperator(Tree tree); +} diff --git a/phylonco-lphy/examples/gompertzCoalescent.lphy b/phylonco-lphy/examples/gompertzCoalescent.lphy index 92628bd..ec7496e 100644 --- a/phylonco-lphy/examples/gompertzCoalescent.lphy +++ b/phylonco-lphy/examples/gompertzCoalescent.lphy @@ -1,16 +1,13 @@ - - data { - L = 500; + L = 1000; } model { - // f0 ~ Beta(alpha=20, beta=7); - N0 ~ LogNormal(meanlog=6,sdlog=0.5); - b ~ LogNormal(meanlog=-0.9, sdlog=0.05); - NInfinity ~ LogNormal(meanlog=10, sdlog=0.5); - gompertzPopFunc = gompertz(N0=N0, b=b, NInfinity=NInfinity); - tree ~ CoalescentPopFunc(popFunc=gompertzPopFunc, n=16); - // rootAge = tree.rootAge(); - D ~ PhyloCTMC(tree=tree, L=L, Q=jukesCantor(), mu=1e-2); + N0 ~ LogNormal(meanlog=8,sdlog=0.5); + f0 ~ Beta(alpha=40, beta=2); + b ~ LogNormal(meanlog=-0.95,sdlog=0.2); + gompertzPopFunc = gompertz(N0=N0,f0=f0, b=b); + tree ~ CoalescentPopFunc(n=40, popFunc=gompertzPopFunc); + //rootAge = tree.rootAge(); + D ~ PhyloCTMC(tree=tree, L=L, Q=jukesCantor(), mu=1e-2); } diff --git a/phylonco-lphy/examples/gompertzGT16.lphy b/phylonco-lphy/examples/gompertzGT16.lphy new file mode 100644 index 0000000..f31002f --- /dev/null +++ b/phylonco-lphy/examples/gompertzGT16.lphy @@ -0,0 +1,22 @@ +data { + L = 1000; + +} +model { +N0 ~ LogNormal(meanlog=9,sdlog=0.3); +f0 ~ Beta(alpha=30, beta=6); +b ~ LogNormal(meanlog=-0.95,sdlog=0.2); +gompertzPopFunc = gompertz(N0=N0,f0=f0, b=b); + +gompertzPopFunc= gompertz(N0=N0,f0=f0, b=b); +ψ ~ CoalescentPopFunc(n=40, popFunc=gompertzPopFunc); + +π ~ Dirichlet(conc=[30.0,3.0,3.0,3.0,3.0,30.0,3.0,3.0,3.0,3.0,30.0,3.0,3.0,3.0,3.0,30.0]); +rates ~ Dirichlet(conc=[1.0, 2.0, 1.0, 1.0, 2.0, 1.0]); +Q = gt16(freq=π, rates=rates); // construct the GT16 instantaneous rate matrix +A ~ PhyloCTMC(L=1000, Q=Q, tree=ψ, dataType=phasedGenotype(), mu=0.01); +// epsilon ~ Beta(alpha=1, beta=50); +// delta ~ Beta(alpha=1, beta=2); +// E ~ GT16ErrorModel(delta=delta, epsilon=epsilon, alignment=A); +D = unphase(A); +} \ No newline at end of file diff --git a/phylonco-lphybeast/src/main/java/phylonco/lphybeast/tobeast/generators/GTUnphaseToBEAST.java b/phylonco-lphybeast/src/main/java/phylonco/lphybeast/tobeast/generators/GTUnphaseToBEAST.java index becfbe5..f7c72f3 100644 --- a/phylonco-lphybeast/src/main/java/phylonco/lphybeast/tobeast/generators/GTUnphaseToBEAST.java +++ b/phylonco-lphybeast/src/main/java/phylonco/lphybeast/tobeast/generators/GTUnphaseToBEAST.java @@ -1,6 +1,8 @@ package phylonco.lphybeast.tobeast.generators; import beast.base.core.BEASTInterface; +import beast.base.evolution.likelihood.GenericTreeLikelihood; +import beast.base.evolution.likelihood.ThreadedTreeLikelihood; import lphy.base.evolution.alignment.Alignment; import lphy.core.model.Generator; import lphy.core.model.GraphicalModelNode; @@ -18,11 +20,13 @@ * E ~ ErrorModel(A); * D = unphase(E); * @author Walter Xie + * @author Kylie Chen + * @author Yuan Xu */ -public class GTUnphaseToBEAST implements GeneratorToBEAST { +public class GTUnphaseToBEAST implements GeneratorToBEAST { @Override - public TreeLikelihoodWithError generatorToBEAST(UnphaseGenotypeAlignment generator, BEASTInterface value, BEASTContext context) { + public GenericTreeLikelihood generatorToBEAST(UnphaseGenotypeAlignment generator, BEASTInterface value, BEASTContext context) { assert value instanceof beast.base.evolution.alignment.Alignment; beast.base.evolution.alignment.Alignment unphasedErrAlignment = (beast.base.evolution.alignment.Alignment)value; @@ -38,26 +42,33 @@ public TreeLikelihoodWithError generatorToBEAST(UnphaseGenotypeAlignment generat } } - // TreeLikelihoodWithError should be already created for err alignment - TreeLikelihoodWithError treeLikelihoodWithError = - (TreeLikelihoodWithError) context.getBEASTObject(errAligGenerator); + GenericTreeLikelihood treeLikelihood = null; - if (treeLikelihoodWithError == null) + // only cast if TreeLikelihoodWithError if using an error model + if (context.getBEASTObject(errAligGenerator) instanceof TreeLikelihoodWithError) { + treeLikelihood = (TreeLikelihoodWithError) context.getBEASTObject(errAligGenerator); + } else { + treeLikelihood = (ThreadedTreeLikelihood) context.getBEASTObject(errAligGenerator); + } + + if (treeLikelihood == null) throw new IllegalArgumentException("Cannot find err alignment tree likelihood !"); - treeLikelihoodWithError.setInputValue("data", unphasedErrAlignment); + treeLikelihood.setInputValue("data", unphasedErrAlignment); - treeLikelihoodWithError.initAndValidate(); - treeLikelihoodWithError.setID(unphasedErrAlignment.getID() + ".treeLikelihood"); + treeLikelihood.initAndValidate(); + treeLikelihood.setID(unphasedErrAlignment.getID() + ".treeLikelihood"); - BEASTInterface errAlignment = context.getBEASTObject(errAlignmentInput); - context.removeBEASTObject(errAlignment); - // remove previous treeLikelihoodWithError added by GT16ErrorModelToBEAST - context.removeBEASTObject(treeLikelihoodWithError); + if (context.getBEASTObject(errAligGenerator) instanceof TreeLikelihoodWithError) { + BEASTInterface errAlignment = context.getBEASTObject(errAlignmentInput); + context.removeBEASTObject(errAlignment); + // remove previous treeLikelihood added by GT16ErrorModelToBEAST + context.removeBEASTObject(treeLikelihood); + } // logging - context.addExtraLoggable(treeLikelihoodWithError); - return treeLikelihoodWithError; + context.addExtraLoggable(treeLikelihood); + return treeLikelihood; } @@ -67,7 +78,7 @@ public Class getGeneratorClass() { } @Override - public Class getBEASTClass() { - return TreeLikelihoodWithError.class; + public Class getBEASTClass() { + return GenericTreeLikelihood.class; } } diff --git a/phylonco-lphybeast/src/main/java/phylonco/lphybeast/tobeast/generators/PopFuncCoalescentToBEAST.java b/phylonco-lphybeast/src/main/java/phylonco/lphybeast/tobeast/generators/PopFuncCoalescentToBEAST.java index 2ed778b..c666bf0 100644 --- a/phylonco-lphybeast/src/main/java/phylonco/lphybeast/tobeast/generators/PopFuncCoalescentToBEAST.java +++ b/phylonco-lphybeast/src/main/java/phylonco/lphybeast/tobeast/generators/PopFuncCoalescentToBEAST.java @@ -1,12 +1,15 @@ package phylonco.lphybeast.tobeast.generators; import beast.base.core.BEASTInterface; +import beast.base.evolution.tree.Tree; import beast.base.evolution.tree.TreeIntervals; +import beast.base.inference.operator.UpDownOperator; import lphy.base.evolution.coalescent.PopulationFunction; import lphy.base.evolution.coalescent.PopulationFunctionCoalescent; import lphy.core.model.Value; import lphybeast.BEASTContext; import lphybeast.GeneratorToBEAST; +import phylonco.beast.evolution.populationmodel.PopFuncWithUpDownOp; //import phylonco.beast.evolution.populationmodel.PopFuncWithUpDownOp; public class PopFuncCoalescentToBEAST implements @@ -41,10 +44,10 @@ public beast.base.evolution.tree.coalescent.Coalescent generatorToBEAST(Populati // populationFunction.initAndValidate(); // } -// if (populationFunction instanceof PopFuncWithUpDownOp popFuncWithUpDownOp) { -// UpDownOperator upDownOperator = popFuncWithUpDownOp.getUpDownOperator((Tree) value); -// context.addExtraOperator(upDownOperator); -// } + if (populationFunction instanceof PopFuncWithUpDownOp popFuncWithUpDownOp) { + UpDownOperator upDownOperator = popFuncWithUpDownOp.getUpDownOperator((Tree) value); + context.addExtraOperator(upDownOperator); + } beastCoalescent.setInputValue("populationModel", populationFunction); diff --git a/phylonco-lphybeast/src/main/java/phylonco/lphybeast/tobeast/values/ExponentialToBEAST.java b/phylonco-lphybeast/src/main/java/phylonco/lphybeast/tobeast/values/ExponentialToBEAST.java index 5e4d235..ba4c87f 100644 --- a/phylonco-lphybeast/src/main/java/phylonco/lphybeast/tobeast/values/ExponentialToBEAST.java +++ b/phylonco-lphybeast/src/main/java/phylonco/lphybeast/tobeast/values/ExponentialToBEAST.java @@ -1,5 +1,6 @@ package phylonco.lphybeast.tobeast.values; +import beast.base.evolution.tree.coalescent.ExponentialGrowth; import beast.base.inference.parameter.RealParameter; import lphy.base.evolution.coalescent.populationmodel.ExponentialPopulation; import lphy.base.evolution.coalescent.populationmodel.ExponentialPopulationFunction; @@ -7,9 +8,6 @@ import lphybeast.BEASTContext; import lphybeast.ValueToBEAST; import lphybeast.tobeast.values.ValueToParameter; -import phylonco.beast.evolution.populationmodel.ExponentialGrowth; - - public class ExponentialToBEAST implements ValueToBEAST { diff --git a/phylonco-lphybeast/src/main/java/phylonco/lphybeast/tobeast/values/GompertzToBEAST.java b/phylonco-lphybeast/src/main/java/phylonco/lphybeast/tobeast/values/GompertzToBEAST.java index 5cb7b5e..b0396ad 100644 --- a/phylonco-lphybeast/src/main/java/phylonco/lphybeast/tobeast/values/GompertzToBEAST.java +++ b/phylonco-lphybeast/src/main/java/phylonco/lphybeast/tobeast/values/GompertzToBEAST.java @@ -22,7 +22,8 @@ public GompertzGrowth valueToBEAST(Value lphyPopFuncVal, BEA // RealParameter N0Param = context.getAsRealParameter(gen.getN0()); RealParameter bParam = context.getAsRealParameter(gen.getB()); - RealParameter NInfinityParam = context.getAsRealParameter(gen.getNInfinity()); + // RealParameter NInfinityParam = context.getAsRealParameter(gen.getNInfinity()); + RealParameter N0Param = context.getAsRealParameter(gen.getN0()); @@ -33,7 +34,7 @@ public GompertzGrowth valueToBEAST(Value lphyPopFuncVal, BEA beastPopFunc.setInputValue("f0", f0Param); beastPopFunc.setInputValue("b", bParam); - beastPopFunc.setInputValue("NInfinity", NInfinityParam); + beastPopFunc.setInputValue("N0", N0Param); beastPopFunc.initAndValidate(); ValueToParameter.setID(beastPopFunc, lphyPopFuncVal);