package beast.math.distributions; import org.apache.commons.math.distribution.ContinuousDistribution; import org.apache.commons.math.distribution.GammaDistributionImpl; import beast.core.Description; import beast.core.Input; import beast.core.parameter.RealParameter; @Description("Gamma distribution. for x>0 g(x;alpha,beta) = 1/Gamma(alpha) beta^alpha} x^{alpha - 1} e^{-\frac{x}{beta}}" + "If the input x is a multidimensional parameter, each of the dimensions is considered as a " + "separate independent component.") public class Gamma extends ParametricDistribution { final public Input<RealParameter> alphaInput = new Input<>("alpha", "shape parameter, defaults to 2"); final public Input<RealParameter> betaInput = new Input<>("beta", "second parameter depends on mode, defaults to 2." + "For mode=ShapeScale beta is interpreted as scale. " + "For mode=ShapeRate beta is interpreted as rate. " + "For mode=ShapeMean beta is interpreted as mean." + "For mode=OneParameter beta is ignored."); public enum mode {ShapeScale, ShapeRate, ShapeMean, OneParameter}; final public Input<mode> modeInput = new Input<>("mode", "determines parameterisation. " + "For ShapeScale beta is interpreted as scale. " + "For ShapeRate beta is interpreted as rate. " + "For ShapeMean beta is interpreted as mean." + "For OneParameter beta is ignored.", mode.ShapeScale, mode.values()); static org.apache.commons.math.distribution.GammaDistribution m_dist = new GammaDistributionImpl(1, 1); mode parameterisation = mode.ShapeScale; @Override public void initAndValidate() { parameterisation = modeInput.get(); refresh(); } /** * make sure internal state is up to date * */ @SuppressWarnings("deprecation") void refresh() { double alpha; double beta = 2.0; if (alphaInput.get() == null) { alpha = 2; } else { alpha = alphaInput.get().getValue(); } switch (parameterisation) { case ShapeScale: if (betaInput.get() != null) { beta = betaInput.get().getValue(); } break; case ShapeRate: if (betaInput.get() != null) { beta = 1.0/betaInput.get().getValue(); } break; case ShapeMean: if (betaInput.get() != null) { beta = betaInput.get().getValue() / alpha; } break; case OneParameter: beta = 1.0 / alpha; break; } m_dist.setAlpha(alpha); m_dist.setBeta(beta); } @Override public ContinuousDistribution getDistribution() { refresh(); return m_dist; } @Override public double getMean() { refresh(); return offsetInput.get() + m_dist.getAlpha() * m_dist.getBeta(); } } // class Gamma