diff --git a/.github/workflows/ci-publish.yml b/.github/workflows/ci-publish.yml new file mode 100644 index 0000000..1023d05 --- /dev/null +++ b/.github/workflows/ci-publish.yml @@ -0,0 +1,55 @@ +name: CI & Publish + +on: + push: + branches: [ master ] + tags: [ 'v*' ] + pull_request: + branches: [ master ] + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up JDK 25 (Azul Zulu) + if: "!startsWith(github.ref, 'refs/tags/v')" + uses: actions/setup-java@v4 + with: + distribution: zulu + java-version: '25' + cache: maven + + - name: Set up JDK 25 (Azul Zulu) for Maven Central + if: startsWith(github.ref, 'refs/tags/v') + uses: actions/setup-java@v4 + with: + distribution: zulu + java-version: '25' + cache: maven + server-id: central + server-username: CENTRAL_USERNAME + server-password: CENTRAL_TOKEN + gpg-private-key: ${{ secrets.GPG_PRIVATE_KEY }} + gpg-passphrase: GPG_PASSPHRASE + + - name: Set release version from tag + if: startsWith(github.ref, 'refs/tags/v') + run: | + VERSION=${GITHUB_REF_NAME#v} + echo "Publishing version: $VERSION" + mvn versions:set -DnewVersion=$VERSION -DgenerateBackupPoms=false + + - name: Build and test + run: mvn verify + + - name: Publish to Maven Central + if: startsWith(github.ref, 'refs/tags/v') + run: mvn deploy -Prelease -DskipTests + env: + CENTRAL_USERNAME: ${{ secrets.CENTRAL_USERNAME }} + CENTRAL_TOKEN: ${{ secrets.CENTRAL_TOKEN }} + GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} diff --git a/README.md b/README.md index d6a7777..e3d3b2e 100644 --- a/README.md +++ b/README.md @@ -7,3 +7,106 @@ Select models through path sampling/stepping stone analysis [Path sampling](http://www.beast2.org/path-sampling/) [Path sampling with a GUI](http://www.beast2.org/2014/07/14/path-sampling-with-a-gui.html) + +## For developer + +Build the package, skipping tests: + +```bash +mvn clean package -DskipTests +``` + +Run an example XML through BEAST: + +```bash +mvn exec:exec -Dbeast.args="src/test/resources/modelselection/examples/normalTest-1.xml" +``` +### Project folder structure + +BEAUti templates and the example XMLs live under `src/`, not root directory: + +``` +src/ +├── main/resources/modelselection/ +│ ├── app/tools/ps.png +│ └── fxtemplates/ +│ └── ModelSelection.xml +└── test/resources/modelselection/examples/ + ├── normalTest-1.xml, normalTest-2.xml, normalTestPS-1.xml, normalTestPS-2.xml, + │ testPairedPathSampler.xml, testPathSampler.xml, testPathSamplerForSimpleTree.xml + └── legacy/ (superseded example XMLs, excluded from the release ZIP) +``` + +`fxtemplates/` is a **main** resource, so it's bundled into the jar (see below). +`examples/` is a **test** resource, so the assembly plugin copies it into the ZIP's +top-level `/examples/` directly from `src/test/resources/`, excluding `legacy/**` +(see `src/assembly/beast-package.xml`). + + +## Releasing + +### Jar folder structure + +The release module jar, bundled into the BEAST package ZIP's `lib/`, contains: + +``` +META-INF/ +├── MANIFEST.MF +└── maven/io.github.beast2-dev/model-selection/ + ├── pom.xml + └── pom.properties +modelselection/ +├── app/tools/ (PathSampler, PathSampleAnalyser, PairedPathSampler*, GeneralisedSteppingStone, ps.png) +├── core/ (CPOLogger) +├── cpo/ (CPOAnalyser, BEASTRunAnalyser + inner classes) +├── fxtemplates/ +│ └── ModelSelection.xml +├── gss/ (GeneralisedSteppingStone*, MCMC2GSS, MCMC2IS, GSSFromFile, TraceLog, ...) +│ ├── coalescent/ +│ └── distribution/ +└── inference/ (PathSampler, PathSamplingStep, PairedPathSampler*, AICMAnalyser, DiffLogger, ...) +version.xml +module-info.class +``` + +`modelselection/fxtemplates/ModelSelection.xml` is loaded via module path resource +lookup at runtime — `src/assembly/beast-package.xml` does not copy it anywhere else in +the ZIP. + +### 1. Maven Central release (JARs) + +Push a `v*` tag to trigger `.github/workflows/ci-publish.yml`, which sets the Maven +version from the tag, builds, tests, GPG-signs, and publishes to Maven Central: + +```bash +git tag v1.7.0 +git push origin v1.7.0 +``` + +Monitor the run at: +https://github.com/BEAST2-Dev/model-selection/actions/workflows/ci-publish.yml + +### 2. GitHub release (BEAST package ZIP) + +First remove `-SNAPSHOT` from `` in `pom.xml` so it matches the release +(e.g. `1.7.0-SNAPSHOT` -> `1.7.0`), then build the installable BEAST package ZIP locally: + +```bash +mvn clean package -DskipTests +``` + +**Note:** if you skip the manual edit above, the build still succeeds, but the module +jar bundled inside the ZIP (`lib/model-selection-.jar`) will carry the +`-SNAPSHOT` suffix — that's meant for dev/testing builds, not an official release. +Alternatively, instead of hand-editing `pom.xml`, run: + +```bash +mvn versions:set -DnewVersion= -DgenerateBackupPoms=false +``` + +The ZIP is written to `target/MODEL_SELECTION.v.zip`. Then manually: + +1. Go to https://github.com/BEAST2-Dev/model-selection/releases/new +2. Choose the matching tag (e.g. `v1.7.0`), fill in the release title/notes +3. Upload `target/MODEL_SELECTION.v.zip` as a release asset +4. Publish diff --git a/build.xml b/build.xml deleted file mode 100644 index 8da5b46..0000000 --- a/build.xml +++ /dev/null @@ -1,246 +0,0 @@ - - - - Build MODEL_SELECTION. - Also used by Hudson MODEL_SELECTION project. - JUnit test is available for this build. - $Id: build_MODEL_SELECTION.xml $ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ** Required file version.xml does not exist. ** - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..b196e93 --- /dev/null +++ b/pom.xml @@ -0,0 +1,284 @@ + + + 4.0.0 + + io.github.beast2-dev + model-selection + 1.7.0-SNAPSHOT + + Model Selection + Select models through path sampling/stepping stone analysis + https://github.com/BEAST2-Dev/model-selection + + + + GNU Lesser General Public License v3.0 + https://www.gnu.org/licenses/lgpl-3.0.html + + + + + + Remco Bouckaert + https://github.com/rbouckaert + + + Guy Baele + + + Marc Suchard + + + + + scm:git:git://github.com/BEAST2-Dev/model-selection.git + scm:git:ssh://github.com:BEAST2-Dev/model-selection.git + https://github.com/BEAST2-Dev/model-selection + + + + UTF-8 + UTF-8 + 25 + + + 2.8.0-beta7 + 25.0.2 + beast.base + beast.base.minimal.BeastMain + + MODEL_SELECTION + + + + + + io.github.compevol + beast-base + ${beast.version} + + + io.github.compevol + beast-pkgmgmt + ${beast.version} + + + + + io.github.compevol + beast-fx + ${beast.version} + true + + + org.openjfx + javafx-controls + ${javafx.version} + true + + + + + io.github.beagle-dev + beagle + 1.0.0 + true + + + + + org.junit.jupiter + junit-jupiter + 5.8.2 + test + + + org.assertj + assertj-core + 3.20.2 + test + + + + + + + src/test/resources + + **/legacy/** + **/reports/** + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.15.0 + + 25 + UTF-8 + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.5.2 + + ${project.build.testOutputDirectory} + + --add-reads model.selection=ALL-UNNAMED + --add-reads beast.base=ALL-UNNAMED + --add-reads beast.pkgmgmt=ALL-UNNAMED + + + ${project.build.outputDirectory}:${settings.localRepository}/io/github/compevol/beast-base/${beast.version}/beast-base-${beast.version}.jar + + + + + + + org.apache.maven.plugins + maven-resources-plugin + 3.3.1 + + + copy-version-xml + generate-resources + copy-resources + + ${project.build.directory} + + + ${project.basedir} + + version.xml + + + + + + + embed-version-xml-in-jar + generate-resources + copy-resources + + ${project.build.outputDirectory} + + + ${project.basedir} + + version.xml + + + + + + + + + + + org.codehaus.mojo + exec-maven-plugin + 3.5.0 + + java + ${project.basedir} + --module-path %classpath -DBEAST_PACKAGE_PATH=${project.build.outputDirectory} -m ${beast.module}/${beast.main} ${beast.args} + + + + + + org.apache.maven.plugins + maven-source-plugin + 3.3.1 + + + attach-sources + jar-no-fork + + + + + + + org.apache.maven.plugins + maven-assembly-plugin + 3.7.1 + + + src/assembly/beast-package.xml + + ${beast.pkg.name}.v${version} + false + + + + beast-package + package + single + + + + + + + + + release + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.11.2 + + none + + + + attach-javadocs + jar + + + + + org.apache.maven.plugins + maven-gpg-plugin + 3.2.7 + + + sign-artifacts + verify + sign + + + + + org.sonatype.central + central-publishing-maven-plugin + 0.11.0 + true + + central + true + published + + + + + + + + diff --git a/src/assembly/beast-package.xml b/src/assembly/beast-package.xml new file mode 100644 index 0000000..2ae9820 --- /dev/null +++ b/src/assembly/beast-package.xml @@ -0,0 +1,51 @@ + + beast-package + + zip + + false + + + + + ${project.basedir}/version.xml + / + + + + ${project.build.directory}/${project.build.finalName}-sources.jar + ${project.build.finalName}-src.jar + / + + + + + + + /lib + true + runtime + + io.github.beast2-dev:model-selection + + + + + + + + + ${project.basedir}/src/test/resources/modelselection/examples + /examples + + legacy/** + reports/** + + + + diff --git a/src/modelselection/app/tools/GeneralisedSteppingStone.java b/src/main/java/modelselection/app/tools/GeneralisedSteppingStone.java similarity index 90% rename from src/modelselection/app/tools/GeneralisedSteppingStone.java rename to src/main/java/modelselection/app/tools/GeneralisedSteppingStone.java index bc20ef7..3233268 100644 --- a/src/modelselection/app/tools/GeneralisedSteppingStone.java +++ b/src/main/java/modelselection/app/tools/GeneralisedSteppingStone.java @@ -2,15 +2,7 @@ -import beastfx.app.beauti.Beauti; -import beastfx.app.inputeditor.BeautiConfig; -import beastfx.app.inputeditor.BeautiDoc; -import beastfx.app.inputeditor.BEASTObjectDialog; -import beastfx.app.inputeditor.BEASTObjectPanel; import beastfx.app.tools.Application; -import beast.base.core.ProgramStatus; -import beast.pkgmgmt.Utils6; -import beastfx.app.util.XMLFile; import modelselection.gss.GSSFromFile; //command line interface to GSS diff --git a/src/modelselection/app/tools/PairedPathSampleAnalyser.java b/src/main/java/modelselection/app/tools/PairedPathSampleAnalyser.java similarity index 91% rename from src/modelselection/app/tools/PairedPathSampleAnalyser.java rename to src/main/java/modelselection/app/tools/PairedPathSampleAnalyser.java index edbcc5f..b62ede0 100644 --- a/src/modelselection/app/tools/PairedPathSampleAnalyser.java +++ b/src/main/java/modelselection/app/tools/PairedPathSampleAnalyser.java @@ -1,16 +1,10 @@ package modelselection.app.tools; -import java.io.File; - -import beastfx.app.beauti.Beauti; -import beastfx.app.inputeditor.BeautiConfig; -import beastfx.app.inputeditor.BeautiDoc; import beastfx.app.inputeditor.BEASTObjectDialog; import beastfx.app.inputeditor.BEASTObjectPanel; +import beastfx.app.inputeditor.BeautiConfig; +import beastfx.app.inputeditor.BeautiDoc; import beastfx.app.tools.Application; -import beast.base.core.BEASTObject; -import beast.base.core.Input; -import modelselection.inference.PathSamplerFromFile; //command line interface to PathSampler public class PairedPathSampleAnalyser { diff --git a/src/modelselection/app/tools/PairedPathSampler.java b/src/main/java/modelselection/app/tools/PairedPathSampler.java similarity index 98% rename from src/modelselection/app/tools/PairedPathSampler.java rename to src/main/java/modelselection/app/tools/PairedPathSampler.java index 4699d98..ecdafc7 100644 --- a/src/modelselection/app/tools/PairedPathSampler.java +++ b/src/main/java/modelselection/app/tools/PairedPathSampler.java @@ -1,16 +1,15 @@ package modelselection.app.tools; -import java.io.File; - import beast.base.core.ProgramStatus; -import beastfx.app.beauti.Beauti; -import beastfx.app.inputeditor.BeautiConfig; -import beastfx.app.inputeditor.BeautiDoc; import beastfx.app.inputeditor.BEASTObjectDialog; import beastfx.app.inputeditor.BEASTObjectPanel; +import beastfx.app.inputeditor.BeautiConfig; +import beastfx.app.inputeditor.BeautiDoc; import beastfx.app.tools.Application; +import java.io.File; + // command line interface to PairedPathSampler public class PairedPathSampler { diff --git a/src/modelselection/app/tools/PathSampleAnalyser.java b/src/main/java/modelselection/app/tools/PathSampleAnalyser.java similarity index 100% rename from src/modelselection/app/tools/PathSampleAnalyser.java rename to src/main/java/modelselection/app/tools/PathSampleAnalyser.java diff --git a/src/modelselection/app/tools/PathSampler.java b/src/main/java/modelselection/app/tools/PathSampler.java similarity index 83% rename from src/modelselection/app/tools/PathSampler.java rename to src/main/java/modelselection/app/tools/PathSampler.java index aac0dea..3d45c28 100644 --- a/src/modelselection/app/tools/PathSampler.java +++ b/src/main/java/modelselection/app/tools/PathSampler.java @@ -1,22 +1,7 @@ package modelselection.app.tools; -import java.util.Optional; - -import beast.base.core.Log; -import beast.base.core.ProgramStatus; -import beastfx.app.beauti.Beauti; -import beastfx.app.inputeditor.BeautiConfig; -import beastfx.app.inputeditor.BeautiDoc; -import beastfx.app.inputeditor.BEASTObjectDialog; -import beastfx.app.inputeditor.BEASTObjectPanel; import beastfx.app.tools.Application; -import beastfx.app.util.Console; -import beastfx.app.util.Utils; -import beastfx.app.util.XMLFile; -import javafx.scene.control.ButtonType; -import modelselection.inference.PathSampleAnalyser; -import modelselection.inference.PathSamplerFromFile; //command line interface to PathSampler public class PathSampler { diff --git a/src/modelselection/core/CPOLogger.java b/src/main/java/modelselection/core/CPOLogger.java similarity index 92% rename from src/modelselection/core/CPOLogger.java rename to src/main/java/modelselection/core/CPOLogger.java index 27c6826..c79effa 100644 --- a/src/modelselection/core/CPOLogger.java +++ b/src/main/java/modelselection/core/CPOLogger.java @@ -1,5 +1,17 @@ package modelselection.core; +import beast.base.core.Description; +import beast.base.core.Input; +import beast.base.core.Input.Validate; +import beast.base.inference.CompoundDistribution; +import beast.base.inference.Distribution; +import beast.base.inference.Logger; +import beast.base.spec.domain.Real; +import beast.base.spec.evolution.likelihood.GenericTreeLikelihood; +import beast.base.spec.evolution.likelihood.ThreadedTreeLikelihood; +import beast.base.spec.evolution.likelihood.TreeLikelihood; +import beast.base.spec.inference.parameter.RealScalarParam; + import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.PrintStream; @@ -7,17 +19,6 @@ import java.util.ArrayList; import java.util.List; -import beast.base.core.Description; -import beast.base.inference.Distribution; -import beast.base.core.Input; -import beast.base.inference.Logger; -import beast.base.core.Input.Validate; -import beast.base.inference.parameter.RealParameter; -import beast.base.inference.CompoundDistribution; -import beast.base.evolution.likelihood.GenericTreeLikelihood; -import beast.base.evolution.likelihood.ThreadedTreeLikelihood; -import beast.base.evolution.likelihood.TreeLikelihood; - @Description("Logs data for pseudo marginal likelihood estimate (see CPOAnalyser for details)") public class CPOLogger extends Logger { public Input likelihoodInput = new Input<>("likelihood", "likelihood distribution, containing one or more treelikilihoods", Validate.REQUIRED); @@ -31,7 +32,7 @@ public CPOLogger() { @Override public void initAndValidate() { - RealParameter p = new RealParameter("1.0"); + RealScalarParam p = new RealScalarParam<>(1.0, Real.INSTANCE); p.setID("dummy"); loggersInput.setValue(p, this); super.initAndValidate(); diff --git a/src/modelselection/cpo/BEASTRunAnalyser.java b/src/main/java/modelselection/cpo/BEASTRunAnalyser.java similarity index 100% rename from src/modelselection/cpo/BEASTRunAnalyser.java rename to src/main/java/modelselection/cpo/BEASTRunAnalyser.java diff --git a/src/modelselection/cpo/CPOAnalyser.java b/src/main/java/modelselection/cpo/CPOAnalyser.java similarity index 92% rename from src/modelselection/cpo/CPOAnalyser.java rename to src/main/java/modelselection/cpo/CPOAnalyser.java index 4b2e455..9c54fd5 100644 --- a/src/modelselection/cpo/CPOAnalyser.java +++ b/src/main/java/modelselection/cpo/CPOAnalyser.java @@ -1,7 +1,30 @@ package modelselection.cpo; +import beast.base.core.*; +import beast.base.evolution.tree.Node; +import beast.base.evolution.tree.Tree; +import beast.base.inference.*; +import beast.base.inference.Runnable; +import beast.base.parser.XMLParser; +import beast.base.parser.XMLParserException; +import beast.base.spec.evolution.branchratemodel.Base; +import beast.base.spec.evolution.likelihood.GenericTreeLikelihood; +import beast.base.spec.evolution.likelihood.ThreadedTreeLikelihood; +import beast.base.spec.evolution.likelihood.TreeLikelihood; +import beast.base.spec.inference.parameter.RealScalarParam; +import beast.base.spec.inference.parameter.RealVectorParam; +import beast.base.spec.type.Vector; +import beast.base.util.Randomizer; +import beastfx.app.tools.Application; +import beastfx.app.tools.LogAnalyser; +import beastfx.app.treeannotator.TreeAnnotator; +import beastfx.app.treeannotator.TreeAnnotator.TreeSet; +import beastfx.app.util.LogFile; +import modelselection.core.CPOLogger; +import org.xml.sax.SAXException; +import javax.xml.parsers.ParserConfigurationException; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; @@ -9,40 +32,6 @@ import java.util.ArrayList; import java.util.List; -import javax.xml.parsers.ParserConfigurationException; - -import org.xml.sax.SAXException; - -import beastfx.app.treeannotator.TreeAnnotator; -import beastfx.app.treeannotator.TreeAnnotator.TreeSet; -import beastfx.app.methodsection.implementation.BranchRateModelMethodsText; -import beastfx.app.tools.Application; -import beastfx.app.util.LogFile; -import beast.base.core.BEASTInterface; -import beast.base.core.Description; -import beast.base.inference.Distribution; -import beast.base.core.Input; -import beast.base.inference.Logger; -import beast.base.inference.MCMC; -import beast.base.core.Param; -import beast.base.inference.Runnable; -import beast.base.inference.State; -import beast.base.inference.StateNode; -import beast.base.inference.parameter.Parameter; -import beast.base.inference.CompoundDistribution; -import beast.base.core.Log; -import beast.base.evolution.branchratemodel.BranchRateModel; -import beast.base.evolution.likelihood.GenericTreeLikelihood; -import beast.base.evolution.likelihood.ThreadedTreeLikelihood; -import beast.base.evolution.likelihood.TreeLikelihood; -import beast.base.evolution.tree.Node; -import beast.base.evolution.tree.Tree; -import beastfx.app.tools.LogAnalyser; -import beast.base.util.Randomizer; -import beast.base.parser.XMLParser; -import beast.base.parser.XMLParserException; -import modelselection.core.CPOLogger; - @Description("Calculate Conditional Predictive Ordinates (CPO), which is a leave one out cross validation measure of fit " + "as described in Lewis et al, Sys Bio, 2014, but adds bootstrap variance estimate as well.") // allows multiple partitions @@ -240,8 +229,8 @@ public CPOTable getCPOTableFromXML() throws SAXException, IOException, ParserCon StateNode stateNode = stateNodes.get(i); String id = stateNode.getID(); String shortid = id.contains(".") ? id.substring(0, id.lastIndexOf('.')): id; - if (stateNode instanceof Parameter && ((Parameter) stateNode).getDimension() > 1) { - Parameter p = ((Parameter) stateNode); + // use Vector + if (stateNode instanceof Vector vector) { id += ".1"; int index = labels.indexOf(shortid); if (index < 0) { @@ -249,8 +238,8 @@ public CPOTable getCPOTableFromXML() throws SAXException, IOException, ParserCon index = labels.indexOf(shortid); } if (index >= 0) { - Double [][] _values = new Double[p.getDimension()][]; - for (int j = 0; j < p.getDimension(); j++) { + Double [][] _values = new Double[vector.size()][]; + for (int j = 0; j < vector.size(); j++) { Double [] v = tracelog.getTrace(1 + index + j); _values[j] = v; } @@ -290,14 +279,24 @@ public CPOTable getCPOTableFromXML() throws SAXException, IOException, ParserCon if (values.get(i) != null) { Object o = values.get(i); StateNode stateNode = stateNodes.get(i); + // scala case if (o instanceof Double[]) { double value = ((Double[])o)[k]; - ((Parameter)stateNode).setValue(value); - } else { +// ((Parameter)stateNode).setValue(value); + if (stateNode instanceof RealScalarParam realScalarParam) + realScalarParam.set(value); +//TODO else if (stateNode instanceof IntScalarParam intScalarParam) +// intScalarParam.set(); + } else { // vector case Double [][] _values = (Double[][]) o; - for (int j = 0; j < _values.length; j++) { - ((Parameter)stateNode).setValue(j, _values[j][k]); - } +// for (int j = 0; j < _values.length; j++) { +// ((Parameter)stateNode).setValue(j, _values[j][k]); +// } + //TODO Int or Bool? + if (stateNode instanceof RealVectorParam realVectorParam) { + for (int j = 0; j < _values.length; j++) + realVectorParam.set(j, _values[j][k]); + } } } } @@ -389,7 +388,7 @@ private boolean hasInput(BEASTInterface clock, String name) { } @Description("clock model that gets its rates from metadata on a newick tree") - class RateByMetaData extends BranchRateModel.Base { + class RateByMetaData extends Base { RateByMetaData(@Param(name="tree",description="beast tree with metadata containing rates")Tree tree) { this.tree = tree; @@ -404,7 +403,7 @@ public double getRateForBranch(Node node) { Node src = tree.getNode(node.getNr()); Object o = src.getMetaData("rate"); if (o == null) { - return meanRateInput.get().getArrayValue(); + return meanRateInput.get().get(); } if (o instanceof Double) { return (Double) o; diff --git a/src/modelselection/gss/GSSFromFile.java b/src/main/java/modelselection/gss/GSSFromFile.java similarity index 100% rename from src/modelselection/gss/GSSFromFile.java rename to src/main/java/modelselection/gss/GSSFromFile.java diff --git a/src/modelselection/gss/GeneralisedSteppingStone.java b/src/main/java/modelselection/gss/GeneralisedSteppingStone.java similarity index 98% rename from src/modelselection/gss/GeneralisedSteppingStone.java rename to src/main/java/modelselection/gss/GeneralisedSteppingStone.java index 29b0e77..71764c0 100644 --- a/src/modelselection/gss/GeneralisedSteppingStone.java +++ b/src/main/java/modelselection/gss/GeneralisedSteppingStone.java @@ -14,10 +14,8 @@ import java.util.List; import java.util.concurrent.CountDownLatch; -import org.apache.commons.math.distribution.BetaDistribution; -import org.apache.commons.math.distribution.BetaDistributionImpl; +import org.apache.commons.statistics.distribution.BetaDistribution; -import beastfx.app.beast.BeastMCMC; import beastfx.app.util.Utils; import beast.base.core.Description; import beast.base.inference.Distribution; @@ -188,7 +186,7 @@ public void run() throws Exception { XMLProducer producer = new XMLProducer(); BetaDistribution betaDistribution = null; if (alphaInput.get() > 0){ - betaDistribution = new BetaDistributionImpl(alphaInput.get(), 1.0); + betaDistribution = BetaDistribution.of(alphaInput.get(), 1.0); } diff --git a/src/modelselection/gss/GeneralisedSteppingStoneStep.java b/src/main/java/modelselection/gss/GeneralisedSteppingStoneStep.java similarity index 71% rename from src/modelselection/gss/GeneralisedSteppingStoneStep.java rename to src/main/java/modelselection/gss/GeneralisedSteppingStoneStep.java index c34d707..93e664d 100644 --- a/src/modelselection/gss/GeneralisedSteppingStoneStep.java +++ b/src/main/java/modelselection/gss/GeneralisedSteppingStoneStep.java @@ -6,7 +6,8 @@ import beast.base.core.Input; import beast.base.inference.CompoundDistribution; import beast.base.inference.Distribution; -import beast.base.inference.Evaluator; +// TODO BEAST3 migration: beast.base.inference.Evaluator was removed in BEAST3; see doLoop() below. +// import beast.base.inference.Evaluator; import beast.base.inference.Operator; import beast.base.util.Randomizer; import modelselection.inference.PathSamplingStep; @@ -67,34 +68,42 @@ protected void doLoop() { Operator operator = operatorSchedule.selectOperator(); //System.out.print("\n" + iSample + " " + operator.getName()+ ":"); - final Distribution evaluatorDistribution = operator.getEvaluatorDistribution(); - Evaluator evaluator = null; - - if (evaluatorDistribution != null) { - evaluator = new Evaluator() { - @Override - public double evaluate() { - double logP = 0.0; - - state.storeCalculationNodes(); - state.checkCalculationNodesDirtiness(); - - try { - logP = evaluatorDistribution.calculateLogP(); - } catch (Exception e) { - e.printStackTrace(); - System.exit(1); - } - - state.restore(); - state.store(currentState); - - return logP; - } - }; - } - - double fLogHastingsRatio = operator.proposal(evaluator); + // TODO BEAST3 migration: beast.base.inference.Evaluator was removed in BEAST3 and + // Operator.proposal(Evaluator) no longer exists (Operator.proposal() is now zero-arg). + // In BEAST2 this evaluator was only ever consumed by SliceOperator.proposal(Evaluator) + // (the only override of proposal(Evaluator)/getEvaluatorDistribution() in beast2/src); + // every other operator's proposal(Evaluator) just delegated to proposal(). SliceOperator + // does not exist in BEAST3 and is not used by this package's own operators/examples, so + // this block was already dead code under BEAST3 and is replaced by operator.proposal(). +// final Distribution evaluatorDistribution = operator.getEvaluatorDistribution(); +// Evaluator evaluator = null; +// +// if (evaluatorDistribution != null) { +// evaluator = new Evaluator() { +// @Override +// public double evaluate() { +// double logP = 0.0; +// +// state.storeCalculationNodes(); +// state.checkCalculationNodesDirtiness(); +// +// try { +// logP = evaluatorDistribution.calculateLogP(); +// } catch (Exception e) { +// e.printStackTrace(); +// System.exit(1); +// } +// +// state.restore(); +// state.store(currentState); +// +// return logP; +// } +// }; +// } +// +// double fLogHastingsRatio = operator.proposal(evaluator); + double fLogHastingsRatio = operator.proposal(); if (fLogHastingsRatio != Double.NEGATIVE_INFINITY) { diff --git a/src/main/java/modelselection/gss/MCMC2Abstract.java b/src/main/java/modelselection/gss/MCMC2Abstract.java new file mode 100644 index 0000000..aa3ffe0 --- /dev/null +++ b/src/main/java/modelselection/gss/MCMC2Abstract.java @@ -0,0 +1,11 @@ +package modelselection.gss; + +import beast.base.inference.MCMC; +import beast.base.inference.Runnable; + +/** + * A module-info.java file cannot contain an abstract class + */ +public abstract class MCMC2Abstract extends Runnable { + protected abstract Runnable newInstance(MCMC mcmc); +} diff --git a/src/modelselection/gss/MCMC2GSS.java b/src/main/java/modelselection/gss/MCMC2GSS.java similarity index 100% rename from src/modelselection/gss/MCMC2GSS.java rename to src/main/java/modelselection/gss/MCMC2GSS.java diff --git a/src/modelselection/gss/MCMC2IS.java b/src/main/java/modelselection/gss/MCMC2IS.java similarity index 83% rename from src/modelselection/gss/MCMC2IS.java rename to src/main/java/modelselection/gss/MCMC2IS.java index 6aa6fa5..1833431 100644 --- a/src/modelselection/gss/MCMC2IS.java +++ b/src/main/java/modelselection/gss/MCMC2IS.java @@ -1,53 +1,41 @@ package modelselection.gss; -import java.io.File; -import java.io.FileWriter; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Set; - -import beastfx.app.util.LogFile; -import beastfx.app.util.OutFile; -import beastfx.app.util.TreeFile; -import beastfx.app.util.XMLFile; -import beast.base.core.BEASTInterface; -import beast.base.core.BEASTObject; -import beast.base.core.Description; -import beast.base.inference.Distribution; -import beast.base.core.Function; -import beast.base.core.Input; -import beast.base.inference.Runnable; -import beast.base.inference.State; -import beast.base.inference.StateNode; -import beast.base.inference.StateNodeInitialiser; -import beast.base.inference.parameter.RealParameter; +import beast.base.core.*; import beast.base.core.Input.Validate; -import beast.base.inference.Logger; -import beast.base.inference.Logger.LOGMODE; -import beast.base.inference.CompoundDistribution; -import beast.base.core.Log; -import beast.base.evolution.tree.coalescent.RandomTree; import beast.base.evolution.tree.Tree; import beast.base.evolution.tree.TreeDistribution; import beast.base.evolution.tree.TreeInterface; -import beast.base.evolution.TreeWithMetaDataLogger; -import beast.base.evolution.tree.MRCAPrior; -import beast.base.inference.MCMC; -import beast.base.parser.JSONProducer; import beast.base.evolution.tree.TreeParser; +import beast.base.inference.*; +import beast.base.inference.Logger.LOGMODE; +import beast.base.inference.Runnable; +import beast.base.parser.JSONProducer; import beast.base.parser.XMLParser; import beast.base.parser.XMLProducer; +import beast.base.spec.evolution.TreeWithMetaDataLogger; +import beast.base.spec.evolution.tree.MRCAPrior; +import beast.base.spec.evolution.tree.coalescent.RandomTree; +import beast.base.spec.inference.distribution.TensorDistribution; +import beast.base.spec.inference.parameter.RealScalarParam; +import beast.base.spec.inference.parameter.RealVectorParam; +import beast.base.spec.type.Tensor; +import beastfx.app.util.LogFile; +import beastfx.app.util.OutFile; +import beastfx.app.util.TreeFile; +import beastfx.app.util.XMLFile; import modelselection.gss.distribution.GSSTreeDistribution; +import modelselection.gss.distribution.GSSTreeDistribution.BranchLengthDistribution; import modelselection.gss.distribution.KernelDensityEstimatorDistribution; import modelselection.gss.distribution.MultivariateKDEDistribution; import modelselection.gss.distribution.NormalKDEDistribution; -import modelselection.gss.distribution.GSSTreeDistribution.BranchLengthDistribution; + +import java.io.File; +import java.io.FileWriter; +import java.util.*; @Description("Convert MCMC analysis to importance sampling analysis like GSS and optionally run the analysis") -abstract public class MCMC2IS extends Runnable { +public class MCMC2IS extends MCMC2Abstract { public Input model1Input = new Input<>("xml", "file name of BEAST XML file containing the model for which to create a GSS XML file for", new XMLFile("examples/normalTest-1XXX.xml"), Validate.REQUIRED); @@ -117,7 +105,10 @@ public void run() throws Exception { Log.warning("Done"); } // save - abstract protected Runnable newInstance(MCMC mcmc); + @Override + protected Runnable newInstance(MCMC mcmc) { + return this; + } private void setUpInitialisers(List initialiser) { for (int i = 0; i < initialiser.size(); i++) { @@ -202,12 +193,14 @@ private CompoundDistribution getAltPrior(CompoundDistribution prior, State state stateNodes.remove(tree); } else if (d instanceof MRCAPrior) { altPrior.add(d); - } else if (d instanceof beast.base.inference.distribution.Prior) { - beast.base.inference.distribution.Prior p = (beast.base.inference.distribution.Prior) d; - Distribution altPriorDist = getAltPriorDist(p.m_x.get(), p.getID()); + } else if (d instanceof TensorDistribution tensorDistribution) { + // BEAST3 dropped Prior -- LogNormal/Gamma/etc. now extend TensorDistribution + // directly and hold their target parameter via paramInput, so d itself plays + // the role the Prior wrapper used to; there is nothing left to unwrap + Tensor param = tensorDistribution.paramInput.get(); + Distribution altPriorDist = getAltPriorDist(param, d.getID()); altPrior.add(altPriorDist); - Object o = ((beast.base.inference.distribution.Prior) d).m_x.get(); - stateNodes.remove(o); + stateNodes.remove(param); } else { Log.warning("Don't know how to handle distribution " + d.getID() + " of type " + d.getClass().getName()); Log.warning("Using "+ d.getID() + " as working distribution"); @@ -217,8 +210,12 @@ private CompoundDistribution getAltPrior(CompoundDistribution prior, State state } for (int i = stateNodes.size() - 1; i >= 0; i--) { StateNode s = stateNodes.get(i); - if (s instanceof RealParameter) { - Distribution altPriorDist = getAltPriorDist(s, s.getID() + "Prior"); + if (s instanceof RealScalarParam realScalarParam) { + Distribution altPriorDist = getAltPriorDist(realScalarParam, s.getID() + "Prior"); + altPrior.add(altPriorDist); + stateNodes.remove(s); + } else if (s instanceof RealVectorParam realVectorParam) { + Distribution altPriorDist = getAltPriorDist(realVectorParam, s.getID() + "Prior"); altPrior.add(altPriorDist); stateNodes.remove(s); } @@ -301,7 +298,7 @@ private TreeInterface getTree(TreeDistribution d) { return tree; } - private Distribution getAltPriorDist(Function f, String priorID) { //beast.base.inference.distribution.Prior d) { + private Distribution getAltPriorDist(Tensor f, String priorID) { //beast.base.inference.distribution.Prior d) { //Function f = String id = ((BEASTInterface) f).getID(); String shortid = id.contains(".") ? id.substring(0, id.lastIndexOf('.')) : id; @@ -342,28 +339,36 @@ private Distribution getAltPriorDist(Function f, String priorID) { //beast.base. Distribution altDist = null; - int dim = f.getDimension(); + int dim = f.size(); if (dim == 1) { altDist = new NormalKDEDistribution(tracelog, label, f); - if (f instanceof RealParameter) { - RealParameter p = (RealParameter) f; + // RealScalarParam + if (f instanceof RealScalarParam realScalarParam) { +// RealParameter p = (RealParameter) f; Double mean = tracelog.getMean(label); - Log.warning("Set value " + p.getID() + " to " + mean); - p.valuesInput.get().set(0, mean); + Log.warning("Set value " + realScalarParam.getID() + " to " + mean); +// p.valuesInput.get().set(0, mean); + realScalarParam.set(mean); } } else { KernelDensityEstimatorDistribution[] multivariateKDE = new KernelDensityEstimatorDistribution[dim]; for (int i = 0; i < dim; i++) { multivariateKDE[i] = new NormalKDEDistribution(tracelog, label + (i+1), null); - if (f instanceof RealParameter) { - RealParameter p = (RealParameter) f; + // RealScalarParam or RealVectorParam + if (f instanceof RealVectorParam realVectorParam) { +// RealParameter p = (RealParameter) f; Double mean = tracelog.getMean(label + (i+1)); - Log.warning("Set value " + p.getID() + "[" + (i+1) + "] to " + mean); - if (i < p.valuesInput.get().size()) { - p.valuesInput.get().set(i, mean); - } else { - p.valuesInput.get().add(mean); - } + Log.warning("Set value " + realVectorParam.getID() + "[" + (i+1) + "] to " + mean); +// if (i < p.valuesInput.get().size()) { +// p.valuesInput.get().set(i, mean); +// } else { +// p.valuesInput.get().add(mean); +// } + if (i < realVectorParam.size()) + realVectorParam.set(i, mean); + else //TODO beast3 cannot append Vector + throw new UnsupportedOperationException(""); + } } altDist = new MultivariateKDEDistribution(multivariateKDE, f); diff --git a/src/modelselection/gss/TraceLog.java b/src/main/java/modelselection/gss/TraceLog.java similarity index 100% rename from src/modelselection/gss/TraceLog.java rename to src/main/java/modelselection/gss/TraceLog.java diff --git a/src/modelselection/gss/TreeFromTreeSetFileInitialiser.java b/src/main/java/modelselection/gss/TreeFromTreeSetFileInitialiser.java similarity index 100% rename from src/modelselection/gss/TreeFromTreeSetFileInitialiser.java rename to src/main/java/modelselection/gss/TreeFromTreeSetFileInitialiser.java diff --git a/src/modelselection/gss/coalescent/CoalescentTreeIntervalStatistic.java b/src/main/java/modelselection/gss/coalescent/CoalescentTreeIntervalStatistic.java similarity index 100% rename from src/modelselection/gss/coalescent/CoalescentTreeIntervalStatistic.java rename to src/main/java/modelselection/gss/coalescent/CoalescentTreeIntervalStatistic.java diff --git a/src/modelselection/gss/coalescent/ExponentialProductPosteriorMeansLikelihood.java b/src/main/java/modelselection/gss/coalescent/ExponentialProductPosteriorMeansLikelihood.java similarity index 98% rename from src/modelselection/gss/coalescent/ExponentialProductPosteriorMeansLikelihood.java rename to src/main/java/modelselection/gss/coalescent/ExponentialProductPosteriorMeansLikelihood.java index 3e73767..167b14c 100644 --- a/src/modelselection/gss/coalescent/ExponentialProductPosteriorMeansLikelihood.java +++ b/src/main/java/modelselection/gss/coalescent/ExponentialProductPosteriorMeansLikelihood.java @@ -49,6 +49,8 @@ public class ExponentialProductPosteriorMeansLikelihood extends Distribution { / private Tree treeModel; private double[] posteriorMeans; + public ExponentialProductPosteriorMeansLikelihood() {} + //make sure to use in combination with coalescentEventsStatistic public ExponentialProductPosteriorMeansLikelihood(Tree treeModel, double[] posteriorMeans) { //super(treeModel); diff --git a/src/modelselection/gss/distribution/ComplexArray.java b/src/main/java/modelselection/gss/distribution/ComplexArray.java similarity index 100% rename from src/modelselection/gss/distribution/ComplexArray.java rename to src/main/java/modelselection/gss/distribution/ComplexArray.java diff --git a/src/modelselection/gss/distribution/FastFourierTransform.java b/src/main/java/modelselection/gss/distribution/FastFourierTransform.java similarity index 100% rename from src/modelselection/gss/distribution/FastFourierTransform.java rename to src/main/java/modelselection/gss/distribution/FastFourierTransform.java diff --git a/src/modelselection/gss/distribution/GSSTreeDistribution.java b/src/main/java/modelselection/gss/distribution/GSSTreeDistribution.java similarity index 95% rename from src/modelselection/gss/distribution/GSSTreeDistribution.java rename to src/main/java/modelselection/gss/distribution/GSSTreeDistribution.java index 66fca75..c6812c8 100644 --- a/src/modelselection/gss/distribution/GSSTreeDistribution.java +++ b/src/main/java/modelselection/gss/distribution/GSSTreeDistribution.java @@ -4,12 +4,9 @@ import java.io.IOException; import java.util.*; -import org.apache.commons.math.MathException; -import org.apache.commons.math.distribution.ContinuousDistribution; -import org.apache.commons.math.distribution.ExponentialDistribution; -import org.apache.commons.math.distribution.ExponentialDistributionImpl; -import org.apache.commons.math.distribution.GammaDistribution; -import org.apache.commons.math.distribution.GammaDistributionImpl; +import org.apache.commons.statistics.distribution.ContinuousDistribution; +import org.apache.commons.statistics.distribution.ExponentialDistribution; +import org.apache.commons.statistics.distribution.GammaDistribution; import beastfx.app.treeannotator.TreeAnnotator; import beastfx.app.treeannotator.TreeAnnotator.TreeSet; @@ -209,19 +206,10 @@ private void processTreeFile() { distributionQuantiles[127] = Double.POSITIVE_INFINITY; logPdistributionQuantiles[127] = -10; for (int i = 1; i < 127; i++) { - try { - distributionQuantiles[i] = branchLengthDistr.inverseCumulativeProbability((i+0.0)/127.0); - logPdistributionQuantiles[i-1] = -Math.log(distributionQuantiles[i] - distributionQuantiles[i-1]); - } catch (MathException e) { - e.printStackTrace(); - throw new RuntimeException(e); - } - } - try { - median = branchLengthDistr.inverseCumulativeProbability(0.5); - } catch (MathException e) { - e.printStackTrace(); + distributionQuantiles[i] = branchLengthDistr.inverseCumulativeProbability((i+0.0)/127.0); + logPdistributionQuantiles[i-1] = -Math.log(distributionQuantiles[i] - distributionQuantiles[i-1]); } + median = branchLengthDistr.inverseCumulativeProbability(0.5); } @@ -239,13 +227,13 @@ private GammaDistribution createGammaDistr() { double alpha = 3 - s + Math.sqrt((s-3)*(s-3)+24*s)/(12*s); double beta = meanLength / alpha; - GammaDistribution distr = new GammaDistributionImpl(alpha, beta); + GammaDistribution distr = GammaDistribution.of(alpha, beta); return distr; } private ExponentialDistribution createExpDistr() { meanLength = meanLength / lengthCount; - ExponentialDistribution distr = new ExponentialDistributionImpl(meanLength); + ExponentialDistribution distr = ExponentialDistribution.of(meanLength); return distr; } diff --git a/src/modelselection/gss/distribution/KernelDensityEstimatorDistribution.java b/src/main/java/modelselection/gss/distribution/KernelDensityEstimatorDistribution.java similarity index 87% rename from src/modelselection/gss/distribution/KernelDensityEstimatorDistribution.java rename to src/main/java/modelselection/gss/distribution/KernelDensityEstimatorDistribution.java index c9bbc32..99cf19e 100644 --- a/src/modelselection/gss/distribution/KernelDensityEstimatorDistribution.java +++ b/src/main/java/modelselection/gss/distribution/KernelDensityEstimatorDistribution.java @@ -27,9 +27,7 @@ import beast.base.core.Description; import beast.base.inference.Distribution; -import beast.base.core.Function; -import beast.base.core.Input; -import beast.base.inference.parameter.Parameter; +import beast.base.spec.type.Tensor; import modelselection.gss.TraceLog; //import dr.math.UnivariateFunction; @@ -38,12 +36,14 @@ * @author Marc Suchard */ @Description("Distribution based on kernel density esitmators") -public abstract class KernelDensityEstimatorDistribution extends Distribution { - protected Function p; +public abstract class KernelDensityEstimatorDistribution extends Distribution { + // real-valued only: this is a kernel density estimate over a continuous trace, so + // Int/Bool-valued params are intentionally out of scope (see modelselection.gss.TraceLog) + protected Tensor p; protected TraceLog traceLog; protected String label; - public KernelDensityEstimatorDistribution(Double[] sample, Double lowerBound, Double upperBound, Double bandWidth, Function p) { + public KernelDensityEstimatorDistribution(Double[] sample, Double lowerBound, Double upperBound, Double bandWidth, Tensor p) { this.p = p; this.sample = new double[sample.length]; for (int i = 0; i < sample.length; i++) { @@ -87,21 +87,13 @@ public double logPdf(double x) { @Override public double calculateLogP() { logP = 0; - if (p instanceof Parameter) { - for (int i = 0; i < p.getDimension(); i++) { - if (p.getArrayValue(i) < (double) ((Parameter)p).getLower()) { - logP = Double.NEGATIVE_INFINITY; - return logP; - } - if (p.getArrayValue(i) > (double) ((Parameter)p).getUpper()) { - logP = Double.NEGATIVE_INFINITY; - return logP; - } - } - } + if (! p.isValid()) { + logP = Double.NEGATIVE_INFINITY; + return logP; + } - for (int i = 0; i < p.getDimension(); i++) { - logP += logPdf(p.getArrayValue(i)); + for (int i = 0; i < p.size(); i++) { + logP += logPdf(p.get(i)); } return logP; } @@ -204,10 +196,10 @@ public String getLabel() { public void setLabel(String label) { this.label = label; } - public Function getX() { + public Tensor getX() { return p; } - public void setX(Function p) { + public void setX(Tensor p) { this.p = p; } } diff --git a/src/modelselection/gss/distribution/LogTransformedNormalKDEDistribution.java b/src/main/java/modelselection/gss/distribution/LogTransformedNormalKDEDistribution.java similarity index 98% rename from src/modelselection/gss/distribution/LogTransformedNormalKDEDistribution.java rename to src/main/java/modelselection/gss/distribution/LogTransformedNormalKDEDistribution.java index b78f8f5..be389e1 100644 --- a/src/modelselection/gss/distribution/LogTransformedNormalKDEDistribution.java +++ b/src/main/java/modelselection/gss/distribution/LogTransformedNormalKDEDistribution.java @@ -26,9 +26,9 @@ package modelselection.gss.distribution; import beast.base.core.Description; -import beast.base.core.Function; import beast.base.core.Param; import beast.base.inference.State; +import beast.base.spec.type.Tensor; import beast.base.util.DiscreteStatistics; //import dr.stats.DiscreteStatistics; //import dr.util.HeapSort; @@ -48,9 +48,12 @@ public class LogTransformedNormalKDEDistribution extends KernelDensityEstimatorD public static final int MINIMUM_GRID_SIZE = 2048; public static final boolean DEBUG = false; + public LogTransformedNormalKDEDistribution() {} + + // real-valued only, same as KernelDensityEstimatorDistribution.p -- Int/Bool-valued params not supported public LogTransformedNormalKDEDistribution(@Param(name="traceLog", description="file containing trace log ") TraceLog traceLog, @Param(name="label",description= "label of the column containing data in the trace file") String label, - @Param(name="x", description="function/statistic to take distribution over") Function p) { + @Param(name="x", description="function/statistic to take distribution over") Tensor p) { this(traceLog.getTrace(label), p); this.traceLog = traceLog; this.label = label; @@ -58,24 +61,24 @@ public LogTransformedNormalKDEDistribution(@Param(name="traceLog", description=" } //the samples should not already be log transformed (the log transformation is done in this class) - public LogTransformedNormalKDEDistribution(Double[] sample, Function p) { + public LogTransformedNormalKDEDistribution(Double[] sample, Tensor p) { this(sample, null, null, null, p); } - public LogTransformedNormalKDEDistribution(Double[] sample, int n, Function p) { + public LogTransformedNormalKDEDistribution(Double[] sample, int n, Tensor p) { this(sample, null, null, null, 3.0, n, p); } - public LogTransformedNormalKDEDistribution(Double[] sample, Double lowerBound, Double upperBound, Double bandWidth, Function p) { + public LogTransformedNormalKDEDistribution(Double[] sample, Double lowerBound, Double upperBound, Double bandWidth, Tensor p) { this(sample, lowerBound, upperBound, bandWidth, 3.0, MINIMUM_GRID_SIZE, p); } public LogTransformedNormalKDEDistribution(Double[] sample, Double lowerBound, Double upperBound, Double bandWidth, - int n, Function p) { + int n, Tensor p) { this(sample, lowerBound, upperBound, bandWidth, 3.0, n, p); } - public LogTransformedNormalKDEDistribution(Double[] sample, Double lowerBound, Double upperBound, Double bandWidth, double cut, int n, Function p) { + public LogTransformedNormalKDEDistribution(Double[] sample, Double lowerBound, Double upperBound, Double bandWidth, double cut, int n, Tensor p) { //first call the super constructor, but immediately overwrite the stored information /* code in super constructor diff --git a/src/modelselection/gss/distribution/LogitTransformedNormalKDEDistribution.java b/src/main/java/modelselection/gss/distribution/LogitTransformedNormalKDEDistribution.java similarity index 96% rename from src/modelselection/gss/distribution/LogitTransformedNormalKDEDistribution.java rename to src/main/java/modelselection/gss/distribution/LogitTransformedNormalKDEDistribution.java index 8797c9a..dcb5e51 100644 --- a/src/modelselection/gss/distribution/LogitTransformedNormalKDEDistribution.java +++ b/src/main/java/modelselection/gss/distribution/LogitTransformedNormalKDEDistribution.java @@ -26,18 +26,19 @@ package modelselection.gss.distribution; -import java.util.List; -import java.util.Random; - import beast.base.core.Description; -import beast.base.core.Function; import beast.base.core.Param; import beast.base.inference.State; +import beast.base.spec.type.Tensor; import beast.base.util.DiscreteStatistics; import beast.base.util.HeapSort; +import modelselection.gss.TraceLog; + +import java.util.List; +import java.util.Random; + //import dr.stats.DiscreteStatistics; //import dr.util.HeapSort; -import modelselection.gss.TraceLog; /** * @author Guy Baele @@ -48,9 +49,12 @@ public class LogitTransformedNormalKDEDistribution extends KernelDensityEstimato public static final int MINIMUM_GRID_SIZE = 2048; public static final boolean DEBUG = false; + public LogitTransformedNormalKDEDistribution() {} + + // real-valued only, same as KernelDensityEstimatorDistribution.p -- Int/Bool-valued params not supported public LogitTransformedNormalKDEDistribution(@Param(name="traceLog", description="trace log ") TraceLog traceLog, @Param(name="label",description= "label of the column containing data in the trace file") String label, - @Param(name="x", description="function/statistic to take distribution over") Function p) { + @Param(name="x", description="function/statistic to take distribution over") Tensor p) { this(traceLog.getTrace(label), p); this.traceLog = traceLog; this.label = label; @@ -58,32 +62,32 @@ public LogitTransformedNormalKDEDistribution(@Param(name="traceLog", description } //the samples should not already be logit transformed (the logit transformation is done in this class) - public LogitTransformedNormalKDEDistribution(Double[] sample, Function p) { + public LogitTransformedNormalKDEDistribution(Double[] sample, Tensor p) { this(sample, 1.0, null, null, null, p); } - public LogitTransformedNormalKDEDistribution(Double[] sample, Double upperLimit, Function p) { + public LogitTransformedNormalKDEDistribution(Double[] sample, Double upperLimit, Tensor p) { this(sample, upperLimit, null, null, null, p); } - public LogitTransformedNormalKDEDistribution(Double[] sample, int n, Function p) { + public LogitTransformedNormalKDEDistribution(Double[] sample, int n, Tensor p) { this(sample, 1.0, null, null, null, 3.0, n, p); } - public LogitTransformedNormalKDEDistribution(Double[] sample, Double upperLimit, int n, Function p) { + public LogitTransformedNormalKDEDistribution(Double[] sample, Double upperLimit, int n, Tensor p) { this(sample, upperLimit, null, null, null, 3.0, n, p); } - public LogitTransformedNormalKDEDistribution(Double[] sample, Double upperLimit, Double lowerBound, Double upperBound, Double bandWidth, Function p) { + public LogitTransformedNormalKDEDistribution(Double[] sample, Double upperLimit, Double lowerBound, Double upperBound, Double bandWidth, Tensor p) { this(sample, upperLimit, lowerBound, upperBound, bandWidth, 3.0, MINIMUM_GRID_SIZE, p); } public LogitTransformedNormalKDEDistribution(Double[] sample, Double upperLimit, Double lowerBound, Double upperBound, Double bandWidth, - int n, Function p) { + int n, Tensor p) { this(sample, upperLimit, lowerBound, upperBound, bandWidth, 3.0, n, p); } - public LogitTransformedNormalKDEDistribution(Double[] sample, Double upperLimit, Double lowerBound, Double upperBound, Double bandWidth, double cut, int n, Function p) { + public LogitTransformedNormalKDEDistribution(Double[] sample, Double upperLimit, Double lowerBound, Double upperBound, Double bandWidth, double cut, int n, Tensor p) { super(sample, lowerBound, upperBound, bandWidth, p); //transform the data to the logit scale and store in logSample diff --git a/src/modelselection/gss/distribution/MultivariateKDEDistribution.java b/src/main/java/modelselection/gss/distribution/MultivariateKDEDistribution.java similarity index 93% rename from src/modelselection/gss/distribution/MultivariateKDEDistribution.java rename to src/main/java/modelselection/gss/distribution/MultivariateKDEDistribution.java index 435ee5b..8231e8f 100644 --- a/src/modelselection/gss/distribution/MultivariateKDEDistribution.java +++ b/src/main/java/modelselection/gss/distribution/MultivariateKDEDistribution.java @@ -26,16 +26,15 @@ package modelselection.gss.distribution; -import java.util.ArrayList; -import java.util.List; -import java.util.Random; - import beast.base.core.Description; -import beast.base.inference.Distribution; -import beast.base.core.Function; import beast.base.core.Input; -import beast.base.core.Param; +import beast.base.inference.Distribution; import beast.base.inference.State; +import beast.base.spec.type.Tensor; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; /** * @author Guy Baele @@ -43,13 +42,13 @@ @Description("Multivariate kernel density esitmators that assumes input variable has independent components") public class MultivariateKDEDistribution extends Distribution { public Input> distInput = new Input<>("dist","distributions, one for each of the dimensions of the parameter", new ArrayList<>()); - public Input xInput = new Input<>("x", "parameter to which this distribution applies"); + public Input xInput = new Input<>("x", "parameter to which this distribution applies"); public static final String TYPE = "multivariateKDE"; public static final boolean DEBUG = false; private KernelDensityEstimatorDistribution[] multivariateKDE; - private Function p; + private Tensor p; private int dimension; //private boolean[] flags; @@ -67,7 +66,7 @@ public void initAndValidate() { public MultivariateKDEDistribution () {} - public MultivariateKDEDistribution (KernelDensityEstimatorDistribution[] multivariateKDE, Function p) { + public MultivariateKDEDistribution (KernelDensityEstimatorDistribution[] multivariateKDE, Tensor p) { this.p = p; if (multivariateKDE.length <= 0) { throw new RuntimeException("Creation error in MultivariateKDEDistribution(Distribution[] multivariateKDE)"); @@ -105,8 +104,8 @@ public MultivariateKDEDistribution (KernelDensityEstimatorDistribution[] multiva @Override public double calculateLogP() { logP = 0; - for (int i = 0; i < p.getDimension(); i++) { - logP += multivariateKDE[i].logPdf((double) p.getArrayValue(i)); + for (int i = 0; i < p.size(); i++) { + logP += multivariateKDE[i].logPdf((double) p.get(i)); } return logP; } diff --git a/src/modelselection/gss/distribution/NormalKDEDistribution.java b/src/main/java/modelselection/gss/distribution/NormalKDEDistribution.java similarity index 94% rename from src/modelselection/gss/distribution/NormalKDEDistribution.java rename to src/main/java/modelselection/gss/distribution/NormalKDEDistribution.java index 34ee361..b7dc5fe 100644 --- a/src/modelselection/gss/distribution/NormalKDEDistribution.java +++ b/src/main/java/modelselection/gss/distribution/NormalKDEDistribution.java @@ -27,20 +27,20 @@ import beast.base.core.Description; -import beast.base.core.Function; import beast.base.core.Input; import beast.base.core.Input.Validate; -import beast.base.core.Param; import beast.base.inference.State; +import beast.base.spec.type.Tensor; import beast.base.util.DiscreteStatistics; import beast.base.util.HeapSort; -//import dr.stats.DiscreteStatistics; -//import dr.util.HeapSort; import modelselection.gss.TraceLog; import java.util.List; import java.util.Random; +//import dr.stats.DiscreteStatistics; +//import dr.util.HeapSort; + /** * @author Marc A. Suchard */ @@ -48,7 +48,8 @@ public class NormalKDEDistribution extends KernelDensityEstimatorDistribution { public Input traceLogInput = new Input<>("traceLog", "file containing trace log", Validate.REQUIRED); public Input labelInput = new Input<>("label", "label of the column containing data in the trace file", Validate.REQUIRED); - public Input xInput = new Input<>("x", "function/statistic to take distribution over"); + // real-valued only, same as KernelDensityEstimatorDistribution.p -- Int/Bool-valued params not supported + public Input> xInput = new Input<>("x", "function/statistic to take distribution over"); public static final int MINIMUM_GRID_SIZE = 512; @@ -88,7 +89,7 @@ public NormalKDEDistribution() {} public NormalKDEDistribution(TraceLog traceLog, String label, - Function p) { + Tensor p) { this(traceLog.getTrace(label), p); this.traceLog = traceLog; this.label = label; @@ -99,21 +100,21 @@ public NormalKDEDistribution(TraceLog traceLog, xInput.setValue(p, this); } - public NormalKDEDistribution(Double[] sample, Function p) { + public NormalKDEDistribution(Double[] sample, Tensor p) { this(sample, null, null, null, p); } - public NormalKDEDistribution(Double[] sample, Double lowerBound, Double upperBound, Double bandWidth, Function p) { + public NormalKDEDistribution(Double[] sample, Double lowerBound, Double upperBound, Double bandWidth, Tensor p) { this(sample, lowerBound, upperBound, bandWidth, 3.0, MINIMUM_GRID_SIZE, p); } public NormalKDEDistribution(Double[] sample, Double lowerBound, Double upperBound, Double bandWidth, - int n, Function p) { + int n, Tensor p) { this(sample, lowerBound, upperBound, bandWidth, 3.0, n, p); } public NormalKDEDistribution(Double[] sample, Double lowerBound, Double upperBound, Double bandWidth, - double cut, int n, Function p) { + double cut, int n, Tensor p) { super(sample, lowerBound, upperBound, bandWidth, p); this.gridSize = Math.max(n, MINIMUM_GRID_SIZE); if (this.gridSize > MINIMUM_GRID_SIZE) { diff --git a/src/modelselection/inference/AICMAnalyser.java b/src/main/java/modelselection/inference/AICMAnalyser.java similarity index 100% rename from src/modelselection/inference/AICMAnalyser.java rename to src/main/java/modelselection/inference/AICMAnalyser.java diff --git a/src/modelselection/inference/DiffLogger.java b/src/main/java/modelselection/inference/DiffLogger.java similarity index 100% rename from src/modelselection/inference/DiffLogger.java rename to src/main/java/modelselection/inference/DiffLogger.java diff --git a/src/modelselection/inference/PairedPathSampleAnalyser.java b/src/main/java/modelselection/inference/PairedPathSampleAnalyser.java similarity index 100% rename from src/modelselection/inference/PairedPathSampleAnalyser.java rename to src/main/java/modelselection/inference/PairedPathSampleAnalyser.java diff --git a/src/modelselection/inference/PairedPathSampler.java b/src/main/java/modelselection/inference/PairedPathSampler.java similarity index 100% rename from src/modelselection/inference/PairedPathSampler.java rename to src/main/java/modelselection/inference/PairedPathSampler.java diff --git a/src/modelselection/inference/PairedPathSamplingStep.java b/src/main/java/modelselection/inference/PairedPathSamplingStep.java similarity index 69% rename from src/modelselection/inference/PairedPathSamplingStep.java rename to src/main/java/modelselection/inference/PairedPathSamplingStep.java index 7195c32..14401dc 100644 --- a/src/modelselection/inference/PairedPathSamplingStep.java +++ b/src/main/java/modelselection/inference/PairedPathSamplingStep.java @@ -4,7 +4,8 @@ import beast.base.core.Description; import beast.base.inference.Distribution; -import beast.base.inference.Evaluator; +// TODO BEAST3 migration: beast.base.inference.Evaluator was removed in BEAST3; see doLoop() below. +// import beast.base.inference.Evaluator; import beast.base.core.Input; import beast.base.inference.Operator; import beast.base.core.Input.Validate; @@ -74,34 +75,42 @@ protected void doLoop() { Operator operator = operatorSchedule.selectOperator(); //System.out.print("\n" + iSample + " " + operator.getName()+ ":"); - final Distribution evaluatorDistribution = operator.getEvaluatorDistribution(); - Evaluator evaluator = null; - - if (evaluatorDistribution != null) { - evaluator = new Evaluator() { - @Override - public double evaluate() { - double logP = 0.0; - - state.storeCalculationNodes(); - state.checkCalculationNodesDirtiness(); - - try { - logP = evaluatorDistribution.calculateLogP(); - } catch (Exception e) { - e.printStackTrace(); - System.exit(1); - } - - state.restore(); - state.store(currentState); - - return logP; - } - }; - } - - double fLogHastingsRatio = operator.proposal(evaluator); + // TODO BEAST3 migration: beast.base.inference.Evaluator was removed in BEAST3 and + // Operator.proposal(Evaluator) no longer exists (Operator.proposal() is now zero-arg). + // In BEAST2 this evaluator was only ever consumed by SliceOperator.proposal(Evaluator) + // (the only override of proposal(Evaluator)/getEvaluatorDistribution() in beast2/src); + // every other operator's proposal(Evaluator) just delegated to proposal(). SliceOperator + // does not exist in BEAST3 and is not used by this package's own operators/examples, so + // this block was already dead code under BEAST3 and is replaced by operator.proposal(). +// final Distribution evaluatorDistribution = operator.getEvaluatorDistribution(); +// Evaluator evaluator = null; +// +// if (evaluatorDistribution != null) { +// evaluator = new Evaluator() { +// @Override +// public double evaluate() { +// double logP = 0.0; +// +// state.storeCalculationNodes(); +// state.checkCalculationNodesDirtiness(); +// +// try { +// logP = evaluatorDistribution.calculateLogP(); +// } catch (Exception e) { +// e.printStackTrace(); +// System.exit(1); +// } +// +// state.restore(); +// state.store(currentState); +// +// return logP; +// } +// }; +// } +// +// double fLogHastingsRatio = operator.proposal(evaluator); + double fLogHastingsRatio = operator.proposal(); if (fLogHastingsRatio != Double.NEGATIVE_INFINITY) { diff --git a/src/modelselection/inference/PathSampleAnalyser.java b/src/main/java/modelselection/inference/PathSampleAnalyser.java similarity index 96% rename from src/modelselection/inference/PathSampleAnalyser.java rename to src/main/java/modelselection/inference/PathSampleAnalyser.java index 0f206b9..909f88e 100644 --- a/src/modelselection/inference/PathSampleAnalyser.java +++ b/src/main/java/modelselection/inference/PathSampleAnalyser.java @@ -8,9 +8,7 @@ import beastfx.app.tools.LogAnalyser; import beast.base.util.Randomizer; -import org.apache.commons.math.MathException; -import org.apache.commons.math.distribution.BetaDistribution; -import org.apache.commons.math.distribution.BetaDistributionImpl; +import org.apache.commons.statistics.distribution.BetaDistribution; import java.io.BufferedReader; import java.io.FileReader; @@ -83,7 +81,7 @@ public double estimateMarginalLikelihood(int nSteps, double alpha, String rootDi } else { BetaDistribution betaDistribution = null; if (alphaInput.get() > 0){ - betaDistribution = new BetaDistributionImpl(alphaInput.get(), 1.0); + betaDistribution = BetaDistribution.of(alphaInput.get(), 1.0); } for (int i = 0; i < nSteps; i++) { @@ -205,7 +203,7 @@ private double mean(Double[] doubles) { return sum; } - private double estimateMarginalLikelihood(List> logdata, Double [] [] marginalLs2, double [] marginalLs, double alpha, int nSteps, double [] betas, boolean verbose) throws MathException, InterruptedException { + private double estimateMarginalLikelihood(List> logdata, Double [] [] marginalLs2, double [] marginalLs, double alpha, int nSteps, double [] betas, boolean verbose) throws InterruptedException { // combine steps double logMarginalL = 0; if (alpha <= 0) { @@ -255,7 +253,7 @@ private double estimateMarginalLikelihood(List> logdata, Double [] //} System.out.println("\nStep theta likelihood contribution ESS"); - BetaDistribution betaDistribution = alpha > 0 ? new BetaDistributionImpl(alpha, 1.0) : null; + BetaDistribution betaDistribution = alpha > 0 ? BetaDistribution.of(alpha, 1.0) : null; for (int i = 0; i < nSteps; i++) { System.out.print(format(i)+" "); double beta = betaDistribution != null ? diff --git a/src/modelselection/inference/PathSampler.java b/src/main/java/modelselection/inference/PathSampler.java similarity index 91% rename from src/modelselection/inference/PathSampler.java rename to src/main/java/modelselection/inference/PathSampler.java index 37554fc..b076af1 100644 --- a/src/modelselection/inference/PathSampler.java +++ b/src/main/java/modelselection/inference/PathSampler.java @@ -1,35 +1,24 @@ package modelselection.inference; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.PrintStream; -import java.io.UnsupportedEncodingException; -import java.net.URISyntaxException; -import java.text.DecimalFormat; -import java.util.List; -import java.util.concurrent.CountDownLatch; - -import org.apache.commons.math.distribution.BetaDistribution; -import org.apache.commons.math.distribution.BetaDistributionImpl; - -import beastfx.app.util.Utils; import beast.base.core.Description; -import beast.base.inference.Distribution; import beast.base.core.Input; -import beast.base.inference.Logger; -import beast.base.inference.MCMC; import beast.base.core.Input.Validate; -import beast.base.inference.CompoundDistribution; import beast.base.core.Log; import beast.base.core.ProgramStatus; -import beast.base.util.Randomizer; +import beast.base.inference.CompoundDistribution; +import beast.base.inference.Distribution; +import beast.base.inference.Logger; +import beast.base.inference.MCMC; import beast.base.parser.XMLProducer; +import beast.base.util.Randomizer; +import beastfx.app.util.Utils; +import org.apache.commons.statistics.distribution.BetaDistribution; +import java.io.*; +import java.net.URISyntaxException; +import java.text.DecimalFormat; +import java.util.List; +import java.util.concurrent.CountDownLatch; @Description("Calculate marginal likelihood through path/stepping stone sampling. " + @@ -180,7 +169,7 @@ public void run() throws Exception { XMLProducer producer = new XMLProducer(); BetaDistribution betaDistribution = null; if (alphaInput.get() > 0){ - betaDistribution = new BetaDistributionImpl(alphaInput.get(), 1.0); + betaDistribution = BetaDistribution.of(alphaInput.get(), 1.0); } @@ -321,8 +310,22 @@ String getCommand(String sStepDir, int iStep) { } sCommand = sCommand.replaceAll("\\$\\(java\\)", javaInJrePath != null ? "\"" + javaInJrePath + "\"" : "java"); sCommand = sCommand.replaceAll("\\$\\(java.library.path\\)", "\"" + sanitise(System.getProperty("java.library.path")) + "\""); -// sCommand = sCommand.replaceAll("\\$\\(java.class.path\\)", "\"" + sanitise(System.getProperty("java.class.path")) + "\""); - sCommand = sCommand.replaceAll("\\$\\(java.class.path\\)", "\"" + sanitise(getLauncherJarPath()) + "\""); + // prefer launcher.jar (packaged BEAST install can self-resolve its classpath from it); + // fall back to this process's own classpath when there's no launcher.jar (e.g. a dev checkout) + String javaClassPath = getLauncherJarPath(); + if (javaClassPath == null) { + javaClassPath = System.getProperty("java.class.path"); + } + sCommand = sCommand.replaceAll("\\$\\(java.class.path\\)", "\"" + sanitise(javaClassPath) + "\""); + // for a JPMS module-path launch (e.g. this dev checkout's bin/beast, using + // --module-path rather than -cp), jdk.module.path reflects the module path this + // very process was started with; scripts that need to spawn a beast.base module + // launch (rather than the classpath-based beast.pkgmgmt.launcher.BeastLauncher) + // should reference $(java.module.path) instead of $(java.class.path) + String javaModulePath = System.getProperty("jdk.module.path"); + if (javaModulePath != null && !javaModulePath.isEmpty()) { + sCommand = sCommand.replaceAll("\\$\\(java.module.path\\)", "\"" + sanitise(javaModulePath) + "\""); + } sCommand = sCommand.replaceAll("beastfx.app.beast.BeastMain", "beast.pkgmgmt.launcher.BeastLauncher"); sCommand = sCommand.replaceAll("beast.app.beastapp.BeastMain", "beast.pkgmgmt.launcher.BeastLauncher"); if (m_sHosts != null) { @@ -339,14 +342,25 @@ String getCommand(String sStepDir, int iStep) { private String getJavaInJrePath() throws URISyntaxException, UnsupportedEncodingException { - File launcherJarFile = new File(getLauncherJarPath()); - String javaInJrePath = launcherJarFile.getParentFile().getParentFile().getAbsolutePath() + "/jre/bin/java"; - + String launcherJarPath = getLauncherJarPath(); + if (launcherJarPath != null) { + File launcherJarFile = new File(launcherJarPath); + String javaInJrePath = launcherJarFile.getParentFile().getParentFile().getAbsolutePath() + "/jre/bin/java"; + if (Utils.isWindows()) { + javaInJrePath += ".exe"; + } + if (new File(javaInJrePath).exists()) { + return javaInJrePath; + } + } + // no launcher.jar (e.g. a dev checkout, not a packaged install): fall back to the + // JRE running this very process, rather than an unqualified "java" resolved via PATH + String javaHomePath = System.getProperty("java.home") + "/bin/java"; if (Utils.isWindows()) { - javaInJrePath += ".exe"; + javaHomePath += ".exe"; } - if (new File(javaInJrePath).exists()) { - return javaInJrePath; + if (new File(javaHomePath).exists()) { + return javaHomePath; } return null; } diff --git a/src/modelselection/inference/PathSamplerFromFile.java b/src/main/java/modelselection/inference/PathSamplerFromFile.java similarity index 100% rename from src/modelselection/inference/PathSamplerFromFile.java rename to src/main/java/modelselection/inference/PathSamplerFromFile.java diff --git a/src/modelselection/inference/PathSamplingStep.java b/src/main/java/modelselection/inference/PathSamplingStep.java similarity index 80% rename from src/modelselection/inference/PathSamplingStep.java rename to src/main/java/modelselection/inference/PathSamplingStep.java index e3be501..7560e22 100644 --- a/src/modelselection/inference/PathSamplingStep.java +++ b/src/main/java/modelselection/inference/PathSamplingStep.java @@ -5,7 +5,8 @@ import beast.base.core.Input; import beast.base.inference.CompoundDistribution; import beast.base.inference.Distribution; -import beast.base.inference.Evaluator; +// TODO BEAST3 migration: beast.base.inference.Evaluator was removed in BEAST3; see doLoop() below. +// import beast.base.inference.Evaluator; import beast.base.inference.Logger; import beast.base.inference.MCMC; import beast.base.inference.Operator; @@ -155,34 +156,42 @@ protected void doLoop() { Operator operator = operatorSchedule.selectOperator(); //System.out.print("\n" + iSample + " " + operator.getName()+ ":"); - final Distribution evaluatorDistribution = operator.getEvaluatorDistribution(); - Evaluator evaluator = null; - - if (evaluatorDistribution != null) { - evaluator = new Evaluator() { - @Override - public double evaluate() { - double logP = 0.0; - - state.storeCalculationNodes(); - state.checkCalculationNodesDirtiness(); - - try { - logP = evaluatorDistribution.calculateLogP(); - } catch (Exception e) { - e.printStackTrace(); - System.exit(1); - } - - state.restore(); - state.store(currentState); - - return logP; - } - }; - } - - double fLogHastingsRatio = operator.proposal(evaluator); + // TODO BEAST3 migration: beast.base.inference.Evaluator was removed in BEAST3 and + // Operator.proposal(Evaluator) no longer exists (Operator.proposal() is now zero-arg). + // In BEAST2 this evaluator was only ever consumed by SliceOperator.proposal(Evaluator) + // (the only override of proposal(Evaluator)/getEvaluatorDistribution() in beast2/src); + // every other operator's proposal(Evaluator) just delegated to proposal(). SliceOperator + // does not exist in BEAST3 and is not used by this package's own operators/examples, so + // this block was already dead code under BEAST3 and is replaced by operator.proposal(). +// final Distribution evaluatorDistribution = operator.getEvaluatorDistribution(); +// Evaluator evaluator = null; +// +// if (evaluatorDistribution != null) { +// evaluator = new Evaluator() { +// @Override +// public double evaluate() { +// double logP = 0.0; +// +// state.storeCalculationNodes(); +// state.checkCalculationNodesDirtiness(); +// +// try { +// logP = evaluatorDistribution.calculateLogP(); +// } catch (Exception e) { +// e.printStackTrace(); +// System.exit(1); +// } +// +// state.restore(); +// state.store(currentState); +// +// return logP; +// } +// }; +// } +// +// double fLogHastingsRatio = operator.proposal(evaluator); + double fLogHastingsRatio = operator.proposal(); if (fLogHastingsRatio != Double.NEGATIVE_INFINITY) { diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java new file mode 100644 index 0000000..9b0ef60 --- /dev/null +++ b/src/main/java/module-info.java @@ -0,0 +1,54 @@ +open module model.selection { + requires beast.base; + requires beast.pkgmgmt; + requires java.xml; + + requires org.apache.commons.statistics.distribution; + + // GUI (optional at runtime) + requires static beast.fx; + requires static javafx.controls; + + // Export all modelselection packages + exports modelselection.app.tools; + exports modelselection.core; + exports modelselection.cpo; + exports modelselection.gss; + exports modelselection.gss.coalescent; + exports modelselection.gss.distribution; + exports modelselection.inference; + + // ServiceLoader service types + uses beast.base.core.BEASTInterface; + // Tell the module system to consume this abstract type + uses modelselection.gss.MCMC2Abstract; + + // Service providers + + provides beast.base.core.BEASTInterface with + modelselection.core.CPOLogger, + modelselection.cpo.BEASTRunAnalyser, + modelselection.cpo.CPOAnalyser, + modelselection.gss.GSSFromFile, + modelselection.gss.GeneralisedSteppingStone, + modelselection.gss.GeneralisedSteppingStoneStep, + modelselection.gss.MCMC2GSS, + modelselection.gss.MCMC2IS, + modelselection.gss.TraceLog, + modelselection.gss.TreeFromTreeSetFileInitialiser, + modelselection.gss.coalescent.ExponentialProductPosteriorMeansLikelihood, + modelselection.gss.distribution.GSSTreeDistribution, + modelselection.gss.distribution.LogTransformedNormalKDEDistribution, + modelselection.gss.distribution.LogitTransformedNormalKDEDistribution, + modelselection.gss.distribution.MultivariateKDEDistribution, + modelselection.gss.distribution.NormalKDEDistribution, + modelselection.inference.AICMAnalyser, + modelselection.inference.DiffLogger, + modelselection.inference.PairedPathSampleAnalyser, + modelselection.inference.PairedPathSampler, + modelselection.inference.PairedPathSamplingStep, + modelselection.inference.PathSampleAnalyser, + modelselection.inference.PathSampler, + modelselection.inference.PathSamplerFromFile, + modelselection.inference.PathSamplingStep; +} diff --git a/fxtemplates/ModelSelection.xml b/src/main/resources/model.selection/fxtemplates/ModelSelection.xml similarity index 50% rename from fxtemplates/ModelSelection.xml rename to src/main/resources/model.selection/fxtemplates/ModelSelection.xml index c8c0103..a9e4b67 100644 --- a/fxtemplates/ModelSelection.xml +++ b/src/main/resources/model.selection/fxtemplates/ModelSelection.xml @@ -1,21 +1,15 @@ - + beastfx.app.inputeditor.BeautiConnector beastfx.app.inputeditor.BeautiSubTemplate -beast.base.inference.distribution.Uniform -beast.base.inference.distribution.Normal -beast.base.inference.distribution.OneOnX -beast.base.inference.distribution.LogNormalDistributionModel -beast.base.inference.distribution.Exponential -beast.base.inference.distribution.Gamma -beast.base.inference.distribution.Beta -beast.base.inference.distribution.LaplaceDistribution -beast.base.inference.distribution.InverseGamma -beast.base.inference.distribution.Prior - + cd $(dir) -$(java) -cp $(java.class.path) beast.pkgmgmt.launcher.BeastLauncher $(resume/overwrite) -seed $(seed) beast.xml +$(java) --module-path $(java.module.path) -m beast.base/beast.base.minimal.BeastMain $(resume/overwrite) -seed $(seed) beast.xml @@ -39,7 +33,7 @@ $(java) -cp $(java.class.path) beast.pkgmgmt.launcher.BeastLauncher $(resume/ove - + @@ -48,7 +42,7 @@ $(java) -cp $(java.class.path) beast.pkgmgmt.launcher.BeastLauncher $(resume/ove - + diff --git a/src/modelselection/app/tools/ps.png b/src/main/resources/modelselection/app/tools/ps.png similarity index 100% rename from src/modelselection/app/tools/ps.png rename to src/main/resources/modelselection/app/tools/ps.png diff --git a/src/test/modelselection/gss/distributions/GSSTreeDistributionTest.java b/src/test/java/test/modelselection/gss/distributions/GSSTreeDistributionTest.java similarity index 82% rename from src/test/modelselection/gss/distributions/GSSTreeDistributionTest.java rename to src/test/java/test/modelselection/gss/distributions/GSSTreeDistributionTest.java index 3fb1a1b..d017e51 100644 --- a/src/test/modelselection/gss/distributions/GSSTreeDistributionTest.java +++ b/src/test/java/test/modelselection/gss/distributions/GSSTreeDistributionTest.java @@ -1,24 +1,17 @@ package test.modelselection.gss.distributions; +import beast.base.evolution.tree.TreeParser; +import beastfx.app.util.TreeFile; +import modelselection.gss.distribution.GSSTreeDistribution; +import org.junit.jupiter.api.Test; + import java.io.FileNotFoundException; -import java.io.IOException; import java.io.PrintStream; -import java.util.ArrayList; -import java.util.List; -import org.junit.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; -import beastfx.app.treeannotator.TreeAnnotator; -import beastfx.app.treeannotator.TreeAnnotator.MemoryFriendlyTreeSet; -import beastfx.app.treeannotator.TreeAnnotator.TreeSet; -import beastfx.app.util.TreeFile; -import beast.base.evolution.tree.Tree; -import beast.base.evolution.tree.TreeParser; -import junit.framework.TestCase; -import modelselection.gss.distribution.GSSTreeDistribution; +public class GSSTreeDistributionTest { -public class GSSTreeDistributionTest extends TestCase { - @Test public void testGSSTreeDistribution() throws FileNotFoundException { TreeParser tree = new TreeParser("((A:0.1,B:0.1):0.1,C:0.2)"); diff --git a/src/test/simstudy/Analyse.java b/src/test/java/test/simstudy/Analyse.java similarity index 100% rename from src/test/simstudy/Analyse.java rename to src/test/java/test/simstudy/Analyse.java diff --git a/src/test/simstudy/GenerateXMLs.java b/src/test/java/test/simstudy/GenerateXMLs.java similarity index 87% rename from src/test/simstudy/GenerateXMLs.java rename to src/test/java/test/simstudy/GenerateXMLs.java index 0a60440..589d379 100644 --- a/src/test/simstudy/GenerateXMLs.java +++ b/src/test/java/test/simstudy/GenerateXMLs.java @@ -3,17 +3,22 @@ // Requirements: the file analysis.xml must be in the directory // from where this script is run. +import beagle.BeagleFlag; +import beast.base.evolution.alignment.Alignment; +import beast.base.evolution.alignment.Sequence; import beast.base.evolution.tree.Tree; import beast.base.inference.Logger; -import beast.base.inference.parameter.RealParameter; import beast.base.parser.NexusParser; import beast.base.parser.XMLParserException; -import beast.base.evolution.alignment.Alignment; -import beast.base.evolution.alignment.Sequence; -import beast.base.evolution.branchratemodel.StrictClockModel; -import beast.base.evolution.sitemodel.SiteModel; -import beast.base.evolution.substitutionmodel.Frequencies; -import beast.base.evolution.substitutionmodel.HKY; +import beast.base.spec.domain.PositiveReal; +import beast.base.spec.domain.UnitInterval; +import beast.base.spec.evolution.branchratemodel.StrictClockModel; +import beast.base.spec.evolution.sitemodel.SiteModel; +import beast.base.spec.evolution.substitutionmodel.Frequencies; +import beast.base.spec.evolution.substitutionmodel.HKY; +import beast.base.spec.inference.parameter.RealScalarParam; +import beast.base.spec.inference.parameter.SimplexParam; +import beast.base.spec.type.Simplex; import beastfx.app.seqgen.MergeDataWith; import beastfx.app.seqgen.SequenceSimulator; @@ -21,8 +26,6 @@ import java.io.IOException; import java.util.List; -import beagle.BeagleFlag; - public class GenerateXMLs { // This script performs a simulation study for the // bModelTest model by sampling from the prior, simulate sequences and @@ -101,21 +104,23 @@ static void process(String dir, String template) throws IllegalArgumentException ); Tree tree = trees.get(i); - RealParameter freqs=new RealParameter("0.25 0.25 0.25 0.25") ; + Simplex freqs = new SimplexParam(new double[]{0.25, 0.25, 0.25, 0.25}); Frequencies f = new Frequencies(); f.initByName("frequencies",freqs); - - HKY hky = new beast.base.evolution.substitutionmodel.HKY(); - hky.initByName("frequencies", f, - "kappa", "1.0" + + HKY hky = new HKY(); + hky.initByName("frequencies", f, + "kappa", new RealScalarParam<>(1.0, PositiveReal.INSTANCE) ); - StrictClockModel clockmodel = new beast.base.evolution.branchratemodel.StrictClockModel(); - clockmodel.initByName("clock.rate","1.0"); + StrictClockModel clockmodel = new StrictClockModel(); + clockmodel.initByName("clock.rate", new RealScalarParam<>(1.0, PositiveReal.INSTANCE)); // change gammaCategoryCount=1 for generating without gamma rate categories SiteModel sitemodel = new SiteModel(); - sitemodel.initByName("gammaCategoryCount", 1, "substModel", hky, "shape", "1.0", "proportionInvariant", "0.0"); + sitemodel.initByName("gammaCategoryCount", 1, "substModel", hky, + "shape", new RealScalarParam<>(1.0, PositiveReal.INSTANCE), + "proportionInvariant", new RealScalarParam<>(0.0, UnitInterval.INSTANCE)); MergeDataWith mergewith = new MergeDataWith(); mergewith.initByName("template", template, "output", dir + "/analysis-out" + i + ".xml"); SequenceSimulator sim = new SequenceSimulator(); diff --git a/examples/normalTest-1.xml b/src/test/resources/modelselection/examples/legacy/normalTest-1.xml similarity index 100% rename from examples/normalTest-1.xml rename to src/test/resources/modelselection/examples/legacy/normalTest-1.xml diff --git a/examples/normalTest-2.xml b/src/test/resources/modelselection/examples/legacy/normalTest-2.xml similarity index 100% rename from examples/normalTest-2.xml rename to src/test/resources/modelselection/examples/legacy/normalTest-2.xml diff --git a/examples/normalTestPS-1.xml b/src/test/resources/modelselection/examples/legacy/normalTestPS-1.xml similarity index 100% rename from examples/normalTestPS-1.xml rename to src/test/resources/modelselection/examples/legacy/normalTestPS-1.xml diff --git a/examples/normalTestPS-2.xml b/src/test/resources/modelselection/examples/legacy/normalTestPS-2.xml similarity index 100% rename from examples/normalTestPS-2.xml rename to src/test/resources/modelselection/examples/legacy/normalTestPS-2.xml diff --git a/examples/testPairedPathSampler.xml b/src/test/resources/modelselection/examples/legacy/testPairedPathSampler.xml similarity index 100% rename from examples/testPairedPathSampler.xml rename to src/test/resources/modelselection/examples/legacy/testPairedPathSampler.xml diff --git a/examples/testPathSampler.xml b/src/test/resources/modelselection/examples/legacy/testPathSampler.xml similarity index 100% rename from examples/testPathSampler.xml rename to src/test/resources/modelselection/examples/legacy/testPathSampler.xml diff --git a/examples/testPathSamplerForSimpleTree.xml b/src/test/resources/modelselection/examples/legacy/testPathSamplerForSimpleTree.xml similarity index 100% rename from examples/testPathSamplerForSimpleTree.xml rename to src/test/resources/modelselection/examples/legacy/testPathSamplerForSimpleTree.xml diff --git a/src/test/resources/modelselection/examples/normalTest-1.xml b/src/test/resources/modelselection/examples/normalTest-1.xml new file mode 100644 index 0000000..aa2334a --- /dev/null +++ b/src/test/resources/modelselection/examples/normalTest-1.xml @@ -0,0 +1,50 @@ + + + + + + 0.0 + 2.0 + + + + + + + + + + + + + -1.532150246 0.04074889315 0.3764286126 -1.273536386 -0.09245518809 -0.08052089396 -0.8836752794 -1.751806433 0.4095952282 1.628965147 0.665399023 0.1235472142 0.7869642234 0.1178040049 0.139374006 2.299191912 -0.3189984415 -0.4214709484 -2.282972059 0.01863195228 + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/resources/modelselection/examples/normalTest-2.xml b/src/test/resources/modelselection/examples/normalTest-2.xml new file mode 100644 index 0000000..4aa1a32 --- /dev/null +++ b/src/test/resources/modelselection/examples/normalTest-2.xml @@ -0,0 +1,50 @@ + + + + + + 0.0 + 2.0 + + + + + + + + + + + + + -1.532150246 0.04074889315 0.3764286126 -1.273536386 -0.09245518809 -0.08052089396 -0.8836752794 -1.751806433 0.4095952282 1.628965147 0.665399023 0.1235472142 0.7869642234 0.1178040049 0.139374006 2.299191912 -0.3189984415 -0.4214709484 -2.282972059 0.01863195228 + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/resources/modelselection/examples/normalTestPS-1.xml b/src/test/resources/modelselection/examples/normalTestPS-1.xml new file mode 100644 index 0000000..90a6fa8 --- /dev/null +++ b/src/test/resources/modelselection/examples/normalTestPS-1.xml @@ -0,0 +1,56 @@ + + + + +cd $(dir) +$(java) --module-path $(java.module.path) -m beast.base/beast.base.minimal.BeastMain $(resume/overwrite) -java -seed $(seed) beast.xml + + + + 0.0 + 2.0 + + + + + + + + + + + + + -1.532150246 0.04074889315 0.3764286126 -1.273536386 -0.09245518809 -0.08052089396 -0.8836752794 -1.751806433 0.4095952282 1.628965147 0.665399023 0.1235472142 0.7869642234 0.1178040049 0.139374006 2.299191912 -0.3189984415 -0.4214709484 -2.282972059 0.01863195228 + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/resources/modelselection/examples/normalTestPS-2.xml b/src/test/resources/modelselection/examples/normalTestPS-2.xml new file mode 100644 index 0000000..3898c52 --- /dev/null +++ b/src/test/resources/modelselection/examples/normalTestPS-2.xml @@ -0,0 +1,56 @@ + + + + +cd $(dir) +$(java) --module-path $(java.module.path) -m beast.base/beast.base.minimal.BeastMain $(resume/overwrite) -seed $(seed) beast.xml + + + + 0.0 + 2.0 + + + + + + + + + + + + + -1.532150246 0.04074889315 0.3764286126 -1.273536386 -0.09245518809 -0.08052089396 -0.8836752794 -1.751806433 0.4095952282 1.628965147 0.665399023 0.1235472142 0.7869642234 0.1178040049 0.139374006 2.299191912 -0.3189984415 -0.4214709484 -2.282972059 0.01863195228 + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/resources/modelselection/examples/testPairedPathSampler.xml b/src/test/resources/modelselection/examples/testPairedPathSampler.xml new file mode 100644 index 0000000..1893368 --- /dev/null +++ b/src/test/resources/modelselection/examples/testPairedPathSampler.xml @@ -0,0 +1,19 @@ + + + +cd $(dir) +$(java) --module-path $(java.module.path) -m beast.base/beast.base.minimal.BeastMain $(resume/overwrite) -java -seed $(seed) beast.xml + + + diff --git a/src/test/resources/modelselection/examples/testPathSampler.xml b/src/test/resources/modelselection/examples/testPathSampler.xml new file mode 100644 index 0000000..2fe4a49 --- /dev/null +++ b/src/test/resources/modelselection/examples/testPathSampler.xml @@ -0,0 +1,111 @@ + + + + + + + + + + + + + +cd $(dir) +$(java) --module-path $(java.module.path) -m beast.base/beast.base.minimal.BeastMain $(resume/overwrite) -seed $(seed) beast.xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/resources/modelselection/examples/testPathSamplerForSimpleTree.xml b/src/test/resources/modelselection/examples/testPathSamplerForSimpleTree.xml new file mode 100644 index 0000000..5faf847 --- /dev/null +++ b/src/test/resources/modelselection/examples/testPathSamplerForSimpleTree.xml @@ -0,0 +1,90 @@ + + + + + + + + + + + + +cd $(dir) +$(java) --module-path $(java.module.path) -m beast.base/beast.base.minimal.BeastMain $(resume/overwrite) -java -seed $(seed) beast.xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/version.xml b/version.xml index d717b06..b672064 100644 --- a/version.xml +++ b/version.xml @@ -1,6 +1,6 @@ - - - + + + +