Skip to content

Migrate input types to BEAST 3 spec interfaces#25

Open
alexeid wants to merge 1 commit into
masterfrom
spec-input-types
Open

Migrate input types to BEAST 3 spec interfaces#25
alexeid wants to merge 1 commit into
masterfrom
spec-input-types

Conversation

@alexeid
Copy link
Copy Markdown
Member

@alexeid alexeid commented May 13, 2026

Summary

Clears the input-rule violations flagged by the beast3-migration linter (17 classes touched, plus one BEAUti editor call-site cast). Mascot Code traffic light goes 🔴 → 🟡.

CalcNodes / Parameters reading scalar inputs

Switch Input<RealScalarParam<Real>> to the read-only Input<RealScalar<Real>> interface and replace per-input somethingIsDirty() with a NeDynamics.isDirtyInput() helper that falls back to the underlying StateNode / CalculationNode dirty signal:

  • ConstantNe, ExponentialNe, LogisticNe

Classes that reshape parameter dimensions at init

Keep the concrete spec param Inputs (setDimension, per-index isDirty(int) aren't on the spec interfaces) and implements StateNodeInitialiser. The marker exempts them from the concrete-spec-param rule, same justification as the Operator exemption — they write into the state nodes they're handed:

  • NeSplineInterpolation, Skygrowth, StructuredSkygrid
  • LogLinearGLM, GlmModel
  • GLMPrior (also swaps Input<ParametricDistribution>Input<ScalarDistribution<?, Double>>)

Distributions that just read

Swap Input<RealVectorParam<? extends Real>> to the RealVector interface and Input<ParametricDistribution> to Input<ScalarDistribution<?, Double>>. Body already uses size() / get(int) / logDensity(double):

  • GrowthRateSmoothingPrior, LogSmoothingPrior

Function-using utilities

Translate Input<Function> to the appropriate spec interface (getDimension()size(), getArrayValue(i)get(i), calcLogP(Function) → manual iid sum of logDensity):

  • LargerThanFunctionRealVector<? extends Real>
  • ErrorSmoothingFunctionRealVector<? extends Real>, ParametricDistributionScalarDistribution<?, Double>
  • MaxRateParametricDistributionScalarDistribution<?, Double> with an iid loop

Legacy CalcNode parent

  • AncestralStateTreeLikelihood swaps its parent import from beast.base.evolution.likelihood.TreeLikelihood (@Deprecated) to beast.base.spec.evolution.likelihood.TreeLikelihood. Protected field surface (m_siteModel.Base, branchRateModel, substitutionModel) matches between legacy and spec parents, so the body needs no further changes.

BoolVector inputs

These two inputs are declared but never read in the body:

  • mappedProbLogger, StructuredTreeLoggerInput<BoolVectorParam>Input<BoolVector>

Editor call-site cast

NeDynamicsListInputEditor disconnects state nodes by getID(); cast to StateNode at the call site so the spec-interface Inputs resolve — runtime values will always be the concrete RealScalarParam.

Not addressed in this PR

Input<List<Function>> remains on mappedProbLogger, StructuredTreeLogger, MappedMascot, and MappedMascotWithTipSampling. Those four are CalcNode / StateNode / Distribution subclasses (not pure Loggers) that implement Loggable as a mixin. The List<Function> metadata is threaded through their toNewick() but never consumed inside the recursion — so the linter Input<@Deprecated> warning is pointing at a vestige. Left untouched pending a refactor of the metadata-logging surface.

Test plan

  • mvn -DskipTests compile clean.
  • mvn test — 8/8 pass.
  • Smoke-test an example XML end-to-end (no exec:exec profile on this repo; consider adding one if you want this baked into CI).

Brings the input-rule violations flagged by the beast3-migration
linter to zero. Three patterns across 17 classes:

CalcNodes / Parameters read from scalar inputs (3 classes):
  Switch Input<RealScalarParam<Real>> to Input<RealScalar<Real>>;
  replace per-input somethingIsDirty() with a NeDynamics.isDirtyInput()
  helper that falls back to the underlying StateNode / CalculationNode
  dirty signal (spec type interfaces deliberately don't expose
  somethingIsDirty()).

    ConstantNe, ExponentialNe, LogisticNe

CalcNodes / Distributions that reshape parameter dimensions at init
(5 classes): keep concrete RealVectorParam / RealScalarParam Inputs
(setDimension and per-index isDirty(int) aren't on the spec
interfaces) and implements StateNodeInitialiser. The marker exempts
them from the concrete-spec-param rule, same justification as the
Operator exemption (these classes write to the state nodes they're
handed).

    NeSplineInterpolation, Skygrowth, StructuredSkygrid,
    LogLinearGLM, GlmModel

Distributions where the input is read-only (3 classes): the holders
just iterate and call get(i) / size(), so the input swaps cleanly to
RealVector interface. Inline ParametricDistribution → spec
ScalarDistribution<?, Double> for the distr inputs; the body already
uses logDensity().

    GrowthRateSmoothingPrior, LogSmoothingPrior, GLMPrior
    (GLMPrior also keeps RealVectorParam / BoolVectorParam Inputs
    plus StateNodeInitialiser, since it calls setDimension at init.)

Function-using utilities (2 classes): swap legacy Input<Function> for
the appropriate spec interface and translate the body calls
(getDimension() → size(), getArrayValue(i) → get(i), calcLogP(Function)
→ manual iid sum of logDensity).

    LargerThan (Function → RealVector<? extends Real>)
    ErrorSmoothing (Function → RealVector<? extends Real>,
        ParametricDistribution → ScalarDistribution<?, Double>)

MaxRate: ParametricDistribution → ScalarDistribution<?, Double> with
an iid loop in place of the legacy calcLogP-over-a-Param-vector.

Legacy CalcNode parent (1 class): AncestralStateTreeLikelihood
swaps its parent import from beast.base.evolution.likelihood.TreeLikelihood
(@deprecated) to beast.base.spec.evolution.likelihood.TreeLikelihood.
Protected field surface (m_siteModel.Base, branchRateModel,
substitutionModel) matches between legacy and spec parents.

Bool inputs that aren't used in the body (2 classes): switch
Input<BoolVectorParam> to the BoolVector interface — these were
dead-but-declared anyway, no behaviour change.

    mappedProbLogger, StructuredTreeLogger

Editor cast (1 class): NeDynamicsListInputEditor disconnects state
nodes by ID. The migrated Inputs return spec interfaces (RealScalar /
RealVector); cast to StateNode at the call site so getID() resolves
— runtime values will always be the concrete param.

Not addressed in this PR:

  * Input<List<Function>> remains on mappedProbLogger,
    StructuredTreeLogger, MappedMascot, and MappedMascotWithTipSampling.
    Those four are CalcNode / StateNode / Distribution subclasses (not
    pure Loggers) that implement Loggable as a mixin to log their own
    tree state. The List<Function> metadata is threaded through their
    toNewick() but never consumed, so the linter Input<@deprecated>
    warning is pointing at a vestige; left untouched here pending a
    refactor of the metadata-logging surface.

Mascot Code traffic light goes 🔴 → 🟡 (cleared input rule and the one
legacy CalcNode parent; the Function-typed Inputs on the four
above-mentioned classes are the remaining yellow). 8/8 tests pass.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant