Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ default List<String> getKeysList() {
*/
void swap(int i, int j);

@Deprecated
@Description("A parameter represents a value in the state space that can be changed by operators.")
abstract class Base<T> extends StateNode implements Parameter<T> {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import beast.pkgmgmt.PackageManager;
import beast.pkgmgmt.launcher.BeastLauncher;
import beastfx.app.beauti.BeautiTabPane;
import beastfx.app.inputeditor.spec.SiteModelInputEditor;
import beastfx.app.util.Alert;
import beastfx.app.util.FXUtils;
import beastfx.app.util.PartitionContextUtil;
Expand Down
91 changes: 42 additions & 49 deletions beast-fx/src/main/java/beastfx/app/inputeditor/IIDInputEditor.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,12 @@
import beast.base.core.Input;
import beast.base.inference.Distribution;
import beast.base.parser.PartitionContext;
import beast.base.spec.domain.*;
import beast.base.spec.domain.Bool;
import beast.base.spec.inference.distribution.IID;
import beast.base.spec.inference.distribution.ScalarDistribution;
import beast.base.spec.inference.distribution.TensorDistribution;
import beast.base.spec.inference.parameter.*;
import beast.base.spec.type.IntVector;
import beast.base.spec.type.RealVector;
import beast.base.spec.type.Scalar;
import beast.base.spec.type.Simplex;
import beast.base.spec.type.*;
import beastfx.app.util.FXUtils;
import javafx.geometry.Insets;
import javafx.scene.Node;
Expand Down Expand Up @@ -175,19 +172,50 @@ private Class<?> getDomain(TensorDistribution<?, ?> value) {
}


/**
* The per-element domain of a vector-valued {@code param} (e.g. {@code Real},
* {@code PositiveReal}, {@code UnitInterval}), used by {@link #isCompatible} to
* decide whether a prior template's declared domain covers it. This is only the
* numeric range each element must fall in -- it says nothing about structural
* constraints across elements (e.g. a Simplex's "elements sum to 1"), which
* {@link #hasSimplexParam} checks separately and independently.
* <p>
* {@code IIDInputEditor} is the dedicated editor registered for {@code IID.class},
* so this only ever runs for IID rows. Every other {@link TensorDistribution} row
* with no dedicated editor of its own (currently just Dirichlet) instead goes through
* {@link TensorDistributionInputEditor}'s identical copy of this method.
*
* @param param the vector-valued input to a {@link TensorDistribution}, e.g. a
* {@code RealVectorParam} or {@code IntVectorParam}
* @return the {@link beast.base.spec.domain.Domain} subclass constraining param's
* elements, or {@code Scalar.class} if param isn't a recognised vector type
*/
private Class<?> getParameterDomain(Object param) {
// a real-valued state-node vector (RealVectorParam, SimplexParam, ...) carries its
// own declared domain (e.g. Real, PositiveReal, UnitInterval) as an input
if (param instanceof RealVectorParam rvp) {
return rvp.domainTypeInput.get().getClass();
}
// same, for an int-valued state-node vector (IntVectorParam, IntSimplexParam, ...)
if (param instanceof IntVectorParam ivp) {
return ivp.domainTypeInput.get().getClass();
}
// not a state-node param but still implements RealVector (e.g. a plain value, not
// backed by an Input) -- fall back to reading the domain off the type itself
if (param instanceof RealVector rs) {
return rs.getDomain().getClass();
}
// same fallback for a non-param IntVector
if (param instanceof IntVector is) {
return is.getDomain().getClass();
}
// boolean vectors have only one possible domain (true/false), so there is nothing
// to look up
if (param instanceof BoolVector) {
return Bool.class;
}
// param isn't any recognised vector type -- shouldn't happen for a vector-valued
// prior's "param" input, but don't guess a domain we can't back up
return Scalar.class;
}

Expand Down Expand Up @@ -351,6 +379,14 @@ private boolean hasSimplexParam(Object param, TensorDistribution<?,?> templateIn
return paramIsSimplex == templateIsSimplex;
}

/**
* Compatible when one domain's range of values fully covers the other's: the
* template's domain is broad enough for the param (e.g. IID's "Real" template
* offered for a PositiveReal-domain vector), or narrow enough to stay within it
* (e.g. a PositiveReal-only template offered for a NonNegativeReal param). Checked
* both ways since neither direction alone covers both cases. Unrelated families
* (Real vs. Int vs. Bool) satisfy neither direction and are correctly rejected.
*/
private boolean isCompatible(Class<?> paramDomain, Class<?> templateDomain, boolean hasSimplexParam) {
if (templateDomain == null) {
// the "no prior" and ScalarDistribution templates should be rejected
Expand All @@ -360,50 +396,7 @@ private boolean isCompatible(Class<?> paramDomain, Class<?> templateDomain, bool
return false;
}

if (Real.class.isAssignableFrom(paramDomain)) {
// check type first
if (!(Real.class.isAssignableFrom(templateDomain))) {
return false;
}
// more range checks here
if (paramDomain == Real.class) {
return true;
}
if (templateDomain == paramDomain) {
return true;
}
if (templateDomain == NonNegativeReal.class && paramDomain == PositiveReal.class) {
return true;
}
if (templateDomain == PositiveReal.class && paramDomain == NonNegativeReal.class) {
return true;
}
return false;
}

if (Int.class.isAssignableFrom(paramDomain)) {
// check type first
if (!(Int.class.isAssignableFrom(templateDomain))) {
return false;
}
// more range checks here
if (paramDomain == Int.class) {
return true;
}
if (templateDomain == paramDomain) {
return true;
}
if (templateDomain == NonNegativeInt.class && paramDomain == PositiveInt.class) {
return true;
}
if (templateDomain == PositiveInt.class && paramDomain == NonNegativeInt.class) {
return true;
}
return false;
}

// don't know how to handle -- err on the side of caution and accept anything
return true;
return templateDomain.isAssignableFrom(paramDomain) || paramDomain.isAssignableFrom(templateDomain);
}


Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package beastfx.app.inputeditor;


import beast.base.spec.inference.distribution.MarkovChainDistribution;
import javafx.scene.control.ComboBox;

/**
* Dedicated editor for a MarkovChainDistribution row in the Priors panel (e.g. Bayesian
* Skyline's "Markov chained prior on population sizes"). Unlike IID or Dirichlet,
* MarkovChainDistribution is not meant to be freely swapped for another prior via the
* generic "distr" combo box: it requires specific wiring (jeffreys/initialMean) that a
* domain-only compatibility check can't validate, and it has no registered subtemplate
* of its own to switch back to. So this editor never offers a picker at all, and (being
* registered for MarkovChainDistribution.class specifically, not TensorDistribution.class)
* it never appears as a candidate in any other row's picker either.
*/
public class MarkovChainDistributionInputEditor extends TensorDistributionInputEditor {

public MarkovChainDistributionInputEditor() {
super();
}
public MarkovChainDistributionInputEditor(BeautiDoc doc) {
super(doc);
}

@Override
public Class<?> type() {
return MarkovChainDistribution.class;
}

@Override
protected ComboBox<BeautiSubTemplate> createComboBox() {
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,11 @@
import java.util.List;





/**
* @deprecated replaced by {@link beastfx.app.inputeditor.spec.ScalarInputEditor}
* or {@link beastfx.app.inputeditor.spec.VectorInputEditor}
*/
@Deprecated
public class ParameterInputEditor extends BEASTObjectInputEditor {
boolean isParametricDistributionParameter = false;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@
import java.util.ArrayList;
import java.util.List;

/**
* @deprecated replaced by {@link beastfx.app.inputeditor.spec.SiteModelInputEditor}
*/
@Deprecated
public class SiteModelInputEditor extends BEASTObjectInputEditor {

IntegerInputEditor categoryCountEditor;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,11 @@
import beast.base.core.Input;
import beast.base.inference.Distribution;
import beast.base.parser.PartitionContext;
import beast.base.spec.domain.*;
import beast.base.spec.domain.Bool;
import beast.base.spec.inference.distribution.ScalarDistribution;
import beast.base.spec.inference.distribution.TensorDistribution;
import beast.base.spec.inference.parameter.*;
import beast.base.spec.type.IntVector;
import beast.base.spec.type.RealVector;
import beast.base.spec.type.Scalar;
import beast.base.spec.type.Simplex;
import beast.base.spec.type.*;
import beastfx.app.util.FXUtils;
import javafx.scene.Node;
import javafx.scene.control.Button;
Expand Down Expand Up @@ -53,7 +50,7 @@ public Class<?> type() {
@Override
public void init(Input<?> input, BEASTInterface beastObject, int itemNr, ExpandOption isExpandOption, boolean addButtons) {
// useDefaultBehavior = !((beastObject instanceof beast.base.inference.distribution.Prior) || beastObject instanceof MRCAPrior || beastObject instanceof TreeDistribution);

if (tensorTemplates == null) {
Input<TensorDistribution<?,?>> _input = new Input<>("param", "dummy input");
_input.setType(TensorDistribution.class);
Expand Down Expand Up @@ -173,19 +170,51 @@ private Class<?> getDomain(TensorDistribution<?, ?> value) {
}


/**
* The per-element domain of a vector-valued {@code param} (e.g. {@code Real},
* {@code PositiveReal}, {@code UnitInterval}), used by {@link #isCompatible} to
* decide whether a prior template's declared domain covers it. This is only the
* numeric range each element must fall in -- it says nothing about structural
* constraints across elements (e.g. a Simplex's "elements sum to 1"), which
* {@link #hasSimplexParam} checks separately and independently.
* <p>
* This editor is the fallback used for any {@link TensorDistribution} row whose
* concrete class has no dedicated editor of its own -- currently Dirichlet, and any
* future spec vector distribution added without one. IID has its own dedicated
* {@link IIDInputEditor}, which carries an identical copy of this method for IID rows
* specifically.
*
* @param param the vector-valued input to a {@link TensorDistribution}, e.g. a
* {@code RealVectorParam} or {@code IntVectorParam}
* @return the {@link beast.base.spec.domain.Domain} subclass constraining param's
* elements, or {@code Scalar.class} if param isn't a recognised vector type
*/
private Class<?> getParameterDomain(Object param) {
// a real-valued state-node vector (RealVectorParam, SimplexParam, ...) carries its
// own declared domain (e.g. Real, PositiveReal, UnitInterval) as an input
if (param instanceof RealVectorParam rvp) {
return rvp.domainTypeInput.get().getClass();
}
// same, for an int-valued state-node vector (IntVectorParam, IntSimplexParam, ...)
if (param instanceof IntVectorParam ivp) {
return ivp.domainTypeInput.get().getClass();
}
// not a state-node param but still implements RealVector (e.g. a plain value, not
// backed by an Input) -- fall back to reading the domain off the type itself
if (param instanceof RealVector rs) {
return rs.getDomain().getClass();
}
// same fallback for a non-param IntVector
if (param instanceof IntVector is) {
return is.getDomain().getClass();
}
// boolean vectors have only one possible domain (true/false), so there is nothing
// to look up
if (param instanceof BoolVector) {
return Bool.class;
}
// param isn't any recognised vector type -- shouldn't happen for a vector-valued
// prior's "param" input, but don't guess a domain we can't back up
return Scalar.class;
}

Expand Down Expand Up @@ -245,7 +274,7 @@ protected void addInputLabel() {

private ComboBox<BeautiSubTemplate> comboBox;

private ComboBox<BeautiSubTemplate> createComboBox() {
protected ComboBox<BeautiSubTemplate> createComboBox() {
ComboBox<BeautiSubTemplate> comboBox = new ComboBox<>();

TensorDistribution<?,?> prior = (TensorDistribution<?,?>) m_beastObject;
Expand Down Expand Up @@ -350,6 +379,14 @@ private boolean hasSimplexParam(Object param, TensorDistribution<?,?> templateIn
return paramIsSimplex == templateIsSimplex;
}

/**
* Compatible when one domain's range of values fully covers the other's: the
* template's domain is broad enough for the param (e.g. IID's "Real" template
* offered for a PositiveReal-domain vector), or narrow enough to stay within it
* (e.g. a PositiveReal-only template offered for a NonNegativeReal param). Checked
* both ways since neither direction alone covers both cases. Unrelated families
* (Real vs. Int vs. Bool) satisfy neither direction and are correctly rejected.
*/
private boolean isCompatible(Class<?> paramDomain, Class<?> templateDomain, boolean hasSimplexParam) {
if (templateDomain == null) {
// the "no prior" and ScalarDistribution templates should be rejected
Expand All @@ -359,50 +396,7 @@ private boolean isCompatible(Class<?> paramDomain, Class<?> templateDomain, bool
return false;
}

if (Real.class.isAssignableFrom(paramDomain)) {
// check type first
if (!(Real.class.isAssignableFrom(templateDomain))) {
return false;
}
// more range checks here
if (paramDomain == Real.class) {
return true;
}
if (templateDomain == paramDomain) {
return true;
}
if (templateDomain == NonNegativeReal.class && paramDomain == PositiveReal.class) {
return true;
}
if (templateDomain == PositiveReal.class && paramDomain == NonNegativeReal.class) {
return true;
}
return false;
}

if (Int.class.isAssignableFrom(paramDomain)) {
// check type first
if (!(Int.class.isAssignableFrom(templateDomain))) {
return false;
}
// more range checks here
if (paramDomain == Int.class) {
return true;
}
if (templateDomain == paramDomain) {
return true;
}
if (templateDomain == NonNegativeInt.class && paramDomain == PositiveInt.class) {
return true;
}
if (templateDomain == PositiveInt.class && paramDomain == NonNegativeInt.class) {
return true;
}
return false;
}

// don't know how to handle -- err on the side of caution and accept anything
return true;
return templateDomain.isAssignableFrom(paramDomain) || paramDomain.isAssignableFrom(templateDomain);
}


Expand Down
Loading
Loading