diff --git a/build.xml b/build.xml
index 2db36273c4..923ccc8224 100644
--- a/build.xml
+++ b/build.xml
@@ -74,7 +74,8 @@
fork="true"
includeantruntime="false"
memoryinitialsize="256m"
- memorymaximumsize="1024m">
+ memorymaximumsize="1024m"
+ encoding="UTF-8">
@@ -255,6 +256,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -262,6 +283,11 @@
+
+
+
+
+
@@ -662,7 +688,7 @@
useJavaXKey="true"
icon="${common_dir}/icons/beast.icns"
jvmversion="${jvm_version}"
- vmoptions="-Xmx2048M"
+ vmoptions="-Xmx2048M -Djava.library.path=/usr/local/lib"
arguments="-window -working -options"
highresolutioncapable="true"
version="${version}"
diff --git a/build_coalsim.xml b/build_coalsim.xml
index 8a66005daf..db081e2209 100644
--- a/build_coalsim.xml
+++ b/build_coalsim.xml
@@ -8,7 +8,7 @@
- 2
+
diff --git a/packaging_tools/mac/universalJavaApplicationStub b/packaging_tools/mac/universalJavaApplicationStub
index e512c58513..43cb6837a0 100755
--- a/packaging_tools/mac/universalJavaApplicationStub
+++ b/packaging_tools/mac/universalJavaApplicationStub
@@ -11,14 +11,14 @@
# #
# @author Tobias Fischer #
# @url https://github.com/tofi86/universalJavaApplicationStub #
-# @date 2018-07-29 #
-# @version 3.0.3 #
+# @date 2023-02-04 #
+# @version 3.3.0 #
# #
##################################################################################
# #
# The MIT License (MIT) #
# #
-# Copyright (c) 2014-2018 Tobias Fischer #
+# Copyright (c) 2014-2023 Tobias Fischer #
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy #
# of this software and associated documentation files (the "Software"), to deal #
@@ -166,6 +166,8 @@ if [ $exitcode -eq 0 ]; then
JavaFolder="${AppleJavaFolder}"
ResourcesFolder="${AppleResourcesFolder}"
+ # set expandable variables
+ APP_ROOT="${AppPackageFolder}"
APP_PACKAGE="${AppPackageFolder}"
JAVAROOT="${AppleJavaFolder}"
USER_HOME="$HOME"
@@ -180,7 +182,7 @@ if [ $exitcode -eq 0 ]; then
# AppPackageRoot is the standard WorkingDirectory when the script is started
WorkingDirectory="${AppPackageRoot}"
fi
- # expand variables $APP_PACKAGE, $JAVAROOT, $USER_HOME
+ # expand variables $APP_PACKAGE, $APP_ROOT, $JAVAROOT, $USER_HOME
WorkingDirectory=$(eval echo "${WorkingDirectory}")
@@ -203,7 +205,7 @@ if [ $exitcode -eq 0 ]; then
else
JVMClassPath=${JVMClassPath_RAW}
fi
- # expand variables $APP_PACKAGE, $JAVAROOT, $USER_HOME
+ # expand variables $APP_PACKAGE, $APP_ROOT, $JAVAROOT, $USER_HOME
JVMClassPath=$(eval echo "${JVMClassPath}")
# read the JVM Options in either Array or String style
@@ -213,6 +215,8 @@ if [ $exitcode -eq 0 ]; then
else
JVMDefaultOptions=${JVMDefaultOptions_RAW}
fi
+ # expand variables $APP_PACKAGE, $APP_ROOT, $JAVAROOT, $USER_HOME (#84)
+ JVMDefaultOptions=$(eval echo "${JVMDefaultOptions}")
# read StartOnMainThread and add as -XstartOnFirstThread
JVMStartOnMainThread=$(plist_get_java ':StartOnMainThread')
@@ -220,9 +224,14 @@ if [ $exitcode -eq 0 ]; then
JVMDefaultOptions+=" -XstartOnFirstThread"
fi
- # read the JVM Arguments as an array and retain spaces
+ # read the JVM Arguments in either Array or String style (#76) and retain spaces
IFS=$'\t\n'
- MainArgs=($(xargs -n1 <<<$(plist_get_java ':Arguments')))
+ MainArgs_RAW=$(plist_get_java ':Arguments' | xargs)
+ if [[ $MainArgs_RAW == *Array* ]] ; then
+ MainArgs=($(xargs -n1 <<<$(plist_get_java ':Arguments' | tr -d '\n' | sed -E 's/Array \{ *(.*) *\}/\1/g' | sed 's/ */ /g')))
+ else
+ MainArgs=($(xargs -n1 <<<$(plist_get_java ':Arguments')))
+ fi
unset IFS
# post processing of the array follows further below...
@@ -240,7 +249,11 @@ else
ResourcesFolder="${OracleResourcesFolder}"
WorkingDirectory="${OracleJavaFolder}"
+ # set expandable variables
APP_ROOT="${AppPackageFolder}"
+ APP_PACKAGE="${AppPackageFolder}"
+ JAVAROOT="${OracleJavaFolder}"
+ USER_HOME="$HOME"
# read the MainClass name
JVMMainClass="$(plist_get ':JVMMainClassName')"
@@ -258,12 +271,12 @@ else
JVMClassPath_RAW=$(plist_get ':JVMClassPath')
if [[ $JVMClassPath_RAW == *Array* ]] ; then
JVMClassPath=.$(plist_get ':JVMClassPath' | grep " " | sed 's/^ */:/g' | tr -d '\n' | xargs)
- # expand variables $APP_PACKAGE, $JAVAROOT, $USER_HOME
+ # expand variables $APP_PACKAGE, $APP_ROOT, $JAVAROOT, $USER_HOME
JVMClassPath=$(eval echo "${JVMClassPath}")
elif [[ ! -z ${JVMClassPath_RAW} ]] ; then
JVMClassPath=${JVMClassPath_RAW}
- # expand variables $APP_PACKAGE, $JAVAROOT, $USER_HOME
+ # expand variables $APP_PACKAGE, $APP_ROOT, $JAVAROOT, $USER_HOME
JVMClassPath=$(eval echo "${JVMClassPath}")
else
@@ -272,8 +285,11 @@ else
# Do NOT expand the default 'AppName.app/Contents/Java/*' classpath (#42)
fi
- # read the JVM Default Options
+ # read the JVM Default Options by parsing the :JVMDefaultOptions
+ # and pulling all values starting with a dash (-)
JVMDefaultOptions=$(plist_get ':JVMDefaultOptions' | grep -o " \-.*" | tr -d '\n' | xargs)
+ # expand variables $APP_PACKAGE, $APP_ROOT, $JAVAROOT, $USER_HOME (#99)
+ JVMDefaultOptions=$(eval echo "${JVMDefaultOptions}")
# read the Main Arguments from JVMArguments key as an array and retain spaces (see #46 for naming details)
IFS=$'\t\n'
@@ -287,6 +303,18 @@ else
fi
+# (#75) check for undefined icons or icon names without .icns extension and prepare
+# an osascript statement for those cases when the icon can be shown in the dialog
+DialogWithIcon=""
+if [ ! -z ${CFBundleIconFile} ]; then
+ if [[ ${CFBundleIconFile} == *.icns ]] && [[ -f "${ResourcesFolder}/${CFBundleIconFile}" ]] ; then
+ DialogWithIcon=" with icon path to resource \"${CFBundleIconFile}\" in bundle (path to me)"
+ elif [[ ${CFBundleIconFile} != *.icns ]] && [[ -f "${ResourcesFolder}/${CFBundleIconFile}.icns" ]] ; then
+ CFBundleIconFile+=".icns"
+ DialogWithIcon=" with icon path to resource \"${CFBundleIconFile}\" in bundle (path to me)"
+ fi
+fi
+
# JVMVersion: post processing and optional splitting
if [[ ${JVMVersion} == *";"* ]]; then
@@ -297,14 +325,14 @@ fi
stub_logger "[JavaRequirement] JVM minimum version: ${JVMVersion}"
stub_logger "[JavaRequirement] JVM maximum version: ${JVMMaxVersion}"
-# MainArgs: replace occurences of $APP_ROOT with its content
+# MainArgs: expand variables $APP_PACKAGE, $APP_ROOT, $JAVAROOT, $USER_HOME
MainArgsArr=()
for i in "${MainArgs[@]}"
do
MainArgsArr+=("$(eval echo "$i")")
done
-# JVMOptions: replace occurences of $APP_ROOT with its content
+# JVMOptions: expand variables $APP_PACKAGE, $APP_ROOT, $JAVAROOT, $USER_HOME
JVMOptionsArr=()
for i in "${JVMOptions[@]}"
do
@@ -315,14 +343,41 @@ done
# internationalized messages
############################################
-LANG=$(defaults read -g AppleLocale)
-stub_logger "[Language] $LANG"
+# supported languages / available translations
+stubLanguages=("de" "en" "es" "fr" "pt-BR" "zh")
+
+# read user preferred languages as defined in macOS System Preferences (#101)
+stub_logger '[LanguageSearch] Checking preferred languages in macOS System Preferences...'
+appleLanguages=($(defaults read -g AppleLanguages | grep '\s"' | tr -d ',' | xargs))
+stub_logger "[LanguageSearch] ... found [${appleLanguages[*]}]"
+
+language=""
+for i in "${appleLanguages[@]}"
+do
+ langValue="${i%-*}"
+ if [[ " ${stubLanguages[*]} " =~ " ${i} " ]]; then
+ stub_logger "[LanguageSearch] ... selected '$i' as the default language for the launcher stub"
+ language=${i}
+ break
+ elif [[ " ${stubLanguages[*]} " =~ " ${langValue} " ]]; then
+ stub_logger "[LanguageSearch] ... selected '$langValue' (from '$i') as the default language for the launcher stub"
+ language=${langValue}
+ break
+ fi
+done
+if [ -z "${language}" ]; then
+ language="en"
+ stub_logger "[LanguageSearch] ... selected fallback 'en' as the default language for the launcher stub"
+fi
+stub_logger "[Language] $language"
+
-# French localization
-if [[ $LANG == fr* ]] ; then
+case "${language}" in
+# French
+fr)
MSG_ERROR_LAUNCHING="ERREUR au lancement de '${CFBundleName}'."
MSG_MISSING_MAINCLASS="'MainClass' n'est pas spécifié.\nL'application Java ne peut pas être lancée."
- MSG_JVMVERSION_REQ_INVALID="La syntaxe de la version Java demandée est invalide: %s\nVeuillez contacter le développeur de l'application."
+ MSG_JVMVERSION_REQ_INVALID="La syntaxe de la version de Java demandée est invalide: %s\nVeuillez contacter le développeur de l'application."
MSG_NO_SUITABLE_JAVA="La version de Java installée sur votre système ne convient pas.\nCe programme nécessite Java %s"
MSG_JAVA_VERSION_OR_LATER="ou ultérieur"
MSG_JAVA_VERSION_LATEST="(dernière mise à jour)"
@@ -330,10 +385,12 @@ if [[ $LANG == fr* ]] ; then
MSG_NO_SUITABLE_JAVA_CHECK="Merci de bien vouloir installer la version de Java requise."
MSG_INSTALL_JAVA="Java doit être installé sur votre système.\nRendez-vous sur java.com et suivez les instructions d'installation..."
MSG_LATER="Plus tard"
- MSG_VISIT_JAVA_DOT_COM="Visiter java.com"
+ MSG_VISIT_JAVA_DOT_COM="Java by Oracle"
+ MSG_VISIT_ADOPTIUM="Java by Adoptium"
+ ;;
-# German localization
-elif [[ $LANG == de* ]] ; then
+# German
+de)
MSG_ERROR_LAUNCHING="FEHLER beim Starten von '${CFBundleName}'."
MSG_MISSING_MAINCLASS="Die 'MainClass' ist nicht spezifiziert!\nDie Java-Anwendung kann nicht gestartet werden!"
MSG_JVMVERSION_REQ_INVALID="Die Syntax der angeforderten Java-Version ist ungültig: %s\nBitte kontaktieren Sie den Entwickler der App."
@@ -344,10 +401,12 @@ elif [[ $LANG == de* ]] ; then
MSG_NO_SUITABLE_JAVA_CHECK="Stellen Sie sicher, dass die angeforderte Java-Version installiert ist."
MSG_INSTALL_JAVA="Auf Ihrem System muss die 'Java'-Software installiert sein.\nBesuchen Sie java.com für weitere Installationshinweise."
MSG_LATER="Später"
- MSG_VISIT_JAVA_DOT_COM="java.com öffnen"
+ MSG_VISIT_JAVA_DOT_COM="Java von Oracle"
+ MSG_VISIT_ADOPTIUM="Java von Adoptium"
+ ;;
-# Simplifyed Chinese localization
-elif [[ $LANG == zh* ]] ; then
+# Simplified Chinese
+zh)
MSG_ERROR_LAUNCHING="无法启动 '${CFBundleName}'."
MSG_MISSING_MAINCLASS="没有指定 'MainClass'!\nJava程序无法启动!"
MSG_JVMVERSION_REQ_INVALID="Java版本参数语法错误: %s\n请联系该应用的开发者。"
@@ -358,10 +417,44 @@ elif [[ $LANG == zh* ]] ; then
MSG_NO_SUITABLE_JAVA_CHECK="请确保系统中安装了所需的Java版本"
MSG_INSTALL_JAVA="你需要在Mac中安装Java运行环境!\n访问 java.com 了解如何安装。"
MSG_LATER="稍后"
- MSG_VISIT_JAVA_DOT_COM="访问 java.com"
-
-# English default localization
-else
+ MSG_VISIT_JAVA_DOT_COM="Java by Oracle"
+ MSG_VISIT_ADOPTIUM="Java by Adoptium"
+ ;;
+
+# Spanish
+es)
+ MSG_ERROR_LAUNCHING="ERROR iniciando '${CFBundleName}'."
+ MSG_MISSING_MAINCLASS="¡'MainClass' no especificada!\n¡La aplicación Java no puede iniciarse!"
+ MSG_JVMVERSION_REQ_INVALID="La sintaxis de la versión Java requerida no es válida: %s\nPor favor, contacte con el desarrollador de la aplicación."
+ MSG_NO_SUITABLE_JAVA="¡No se encontró una versión de Java adecuada en su sistema!\nEste programa requiere Java %s"
+ MSG_JAVA_VERSION_OR_LATER="o posterior"
+ MSG_JAVA_VERSION_LATEST="(ultima actualización)"
+ MSG_JAVA_VERSION_MAX="superior a %s"
+ MSG_NO_SUITABLE_JAVA_CHECK="Asegúrese de instalar la versión Java requerida."
+ MSG_INSTALL_JAVA="¡Necesita tener JAVA instalado en su Mac!\nVisite java.com para consultar las instrucciones para su instalación..."
+ MSG_LATER="Más tarde"
+ MSG_VISIT_JAVA_DOT_COM="Java de Oracle"
+ MSG_VISIT_ADOPTIUM="Java de Adoptium"
+ ;;
+
+# Brazilian Portuguese
+pt-BR)
+ MSG_ERROR_LAUNCHING="ERRO iniciando '${CFBundleName}'."
+ MSG_MISSING_MAINCLASS="'MainClass' não foi definida!\nA aplicação java não poderá ser iniciada!"
+ MSG_JVMVERSION_REQ_INVALID="A sintaxe da versão Java requerida não é valida: %s\nPor favor contacte o desenvolvedor dessa aplicação."
+ MSG_NO_SUITABLE_JAVA="Não foi encontrado uma versão Java compatível no seu sistema!\nEsta aplicação precisa do Java %s"
+ MSG_JAVA_VERSION_OR_LATER="ou maior"
+ MSG_JAVA_VERSION_LATEST="(última atualização)"
+ MSG_JAVA_VERSION_MAX="máxima %s"
+ MSG_NO_SUITABLE_JAVA_CHECK="Verifique se instalou a versão Java necessária."
+ MSG_INSTALL_JAVA="Você precisa instalar o JAVA no seu Mac!\nPor favor, visite java.com para instruções de instalação..."
+ MSG_LATER="Depois"
+ MSG_VISIT_JAVA_DOT_COM="Java por Oracle"
+ MSG_VISIT_ADOPTIUM="Java por Adoptium"
+ ;;
+
+# English | default
+en|*)
MSG_ERROR_LAUNCHING="ERROR launching '${CFBundleName}'."
MSG_MISSING_MAINCLASS="'MainClass' isn't specified!\nJava application cannot be started!"
MSG_JVMVERSION_REQ_INVALID="The syntax of the required Java version is invalid: %s\nPlease contact the App developer."
@@ -372,8 +465,10 @@ else
MSG_NO_SUITABLE_JAVA_CHECK="Make sure you install the required Java version."
MSG_INSTALL_JAVA="You need to have JAVA installed on your Mac!\nVisit java.com for installation instructions..."
MSG_LATER="Later"
- MSG_VISIT_JAVA_DOT_COM="Visit java.com"
-fi
+ MSG_VISIT_JAVA_DOT_COM="Java by Oracle"
+ MSG_VISIT_ADOPTIUM="Java by Adoptium"
+ ;;
+esac
@@ -456,7 +551,7 @@ function get_comparable_java_version() {
################################################################################
function is_valid_requirement_pattern() {
local java_req=$1
- java8pattern='1\.[4-8](\.0)?(\.0_[0-9]+)?[*+]?'
+ java8pattern='1\.[4-8](\.[0-9]+)?(\.0_[0-9]+)?[*+]?'
java9pattern='(9|1[0-9])(-ea|[*+]|(\.[0-9]+){1,2}[*+]?)?'
# test matches either old Java versioning scheme (up to 1.8) or new scheme (starting with 9)
if [[ ${java_req} =~ ^(${java8pattern}|${java9pattern})$ ]]; then
@@ -489,20 +584,28 @@ if [ -n "$JAVA_HOME" ] ; then
if [[ $JAVA_HOME == /* ]] ; then
# if "$JAVA_HOME" starts with a Slash it's an absolute path
JAVACMD="$JAVA_HOME/bin/java"
+ stub_logger "[JavaSearch] ... parsing JAVA_HOME as absolute path to the executable '$JAVACMD'"
else
# otherwise it's a relative path to "$AppPackageFolder"
JAVACMD="$AppPackageFolder/$JAVA_HOME/bin/java"
+ stub_logger "[JavaSearch] ... parsing JAVA_HOME as relative path inside the App bundle to the executable '$JAVACMD'"
fi
JAVACMD_version=$(get_comparable_java_version $(get_java_version_from_cmd "${JAVACMD}"))
else
- stub_logger "[JavaSearch] ... didn't found JAVA_HOME"
+ stub_logger "[JavaSearch] ... haven't found JAVA_HOME"
fi
# check for any other or a specific Java version
# also if $JAVA_HOME exists but isn't executable
if [ -z "${JAVACMD}" ] || [ ! -x "${JAVACMD}" ] ; then
- stub_logger "[JavaSearch] Checking for JavaVirtualMachines on the system ..."
+
+ # add a warning in the syslog if JAVA_HOME is not executable or not found (#100)
+ if [ -n "$JAVA_HOME" ] ; then
+ stub_logger "[JavaSearch] ... but no 'java' executable was found at the JAVA_HOME location!"
+ fi
+
+ stub_logger "[JavaSearch] Searching for JavaVirtualMachines on the system ..."
# reset variables
JAVACMD=""
JAVACMD_version=""
@@ -513,7 +616,7 @@ if [ -z "${JAVACMD}" ] || [ ! -x "${JAVACMD}" ] ; then
# log exit cause
stub_logger "[EXIT 4] ${MSG_JVMVERSION_REQ_INVALID_EXPANDED}"
# display error message with AppleScript
- osascript -e "tell application \"System Events\" to display dialog \"${MSG_ERROR_LAUNCHING}\n\n${MSG_JVMVERSION_REQ_INVALID_EXPANDED}\" with title \"${CFBundleName}\" buttons {\" OK \"} default button 1 with icon path to resource \"${CFBundleIconFile}\" in bundle (path to me)"
+ osascript -e "tell application \"System Events\" to display dialog \"${MSG_ERROR_LAUNCHING}\n\n${MSG_JVMVERSION_REQ_INVALID_EXPANDED}\" with title \"${CFBundleName}\" buttons {\" OK \"} default button 1${DialogWithIcon}"
# exit with error
exit 4
fi
@@ -523,7 +626,7 @@ if [ -z "${JAVACMD}" ] || [ ! -x "${JAVACMD}" ] ; then
# log exit cause
stub_logger "[EXIT 5] ${MSG_JVMVERSION_REQ_INVALID_EXPANDED}"
# display error message with AppleScript
- osascript -e "tell application \"System Events\" to display dialog \"${MSG_ERROR_LAUNCHING}\n\n${MSG_JVMVERSION_REQ_INVALID_EXPANDED}\" with title \"${CFBundleName}\" buttons {\" OK \"} default button 1 with icon path to resource \"${CFBundleIconFile}\" in bundle (path to me)"
+ osascript -e "tell application \"System Events\" to display dialog \"${MSG_ERROR_LAUNCHING}\n\n${MSG_JVMVERSION_REQ_INVALID_EXPANDED}\" with title \"${CFBundleName}\" buttons {\" OK \"} default button 1${DialogWithIcon}"
# exit with error
exit 5
fi
@@ -531,15 +634,41 @@ if [ -z "${JAVACMD}" ] || [ ! -x "${JAVACMD}" ] ; then
# find installed JavaVirtualMachines (JDK + JRE)
allJVMs=()
- # read JDK's from '/usr/libexec/java_home -V' command
- while read -r line; do
- version=$(echo $line | awk -F $',' '{print $1;}')
- path=$(echo $line | awk -F $'" ' '{print $2;}')
- path+="/bin/java"
- allJVMs+=("$version:$path")
- done < <(/usr/libexec/java_home -V 2>&1 | grep '^[[:space:]]')
- # unset while loop variables
- unset version path
+
+ # read JDK's from '/usr/libexec/java_home --xml' command with PlistBuddy and a custom Dict iterator
+ # idea: https://stackoverflow.com/a/14085460/1128689 and https://scriptingosx.com/2018/07/parsing-dscl-output-in-scripts/
+ javaXml=$(/usr/libexec/java_home --xml)
+ javaCounter=$(/usr/libexec/PlistBuddy -c "Print" /dev/stdin <<< $javaXml | grep "Dict" | wc -l | tr -d ' ')
+
+ # iterate over all Dict entries
+ # but only if there are any JVMs at all (#93)
+ if [ "$javaCounter" -gt "0" ] ; then
+ for idx in $(seq 0 $((javaCounter - 1)))
+ do
+ version=$(/usr/libexec/PlistBuddy -c "print :$idx:JVMVersion" /dev/stdin <<< $javaXml)
+ path=$(/usr/libexec/PlistBuddy -c "print :$idx:JVMHomePath" /dev/stdin <<< $javaXml)
+ path+="/bin/java"
+ allJVMs+=("$version:$path")
+ done
+ # unset for loop variables
+ unset version path
+ fi
+
+ # add SDKMAN! java versions (#95)
+ if [ -d ~/.sdkman/candidates/java/ ] ; then
+ for sdkjdk in ~/.sdkman/candidates/java/*/
+ do
+ if [[ ${sdkjdk} =~ /current/$ ]] ; then
+ continue
+ fi
+
+ sdkjdkcmd="${sdkjdk}bin/java"
+ version=$(get_java_version_from_cmd "${sdkjdkcmd}")
+ allJVMs+=("$version:$sdkjdkcmd")
+ done
+ # unset for loop variables
+ unset version
+ fi
# add Apple JRE if available
if [ -x "${apple_jre_plugin}" ] ; then
@@ -559,6 +688,9 @@ if [ -z "${JAVACMD}" ] || [ ! -x "${JAVACMD}" ] ; then
# determine JVMs matching the min/max version requirement
+
+ stub_logger "[JavaSearch] Filtering the result list for JVMs matching the min/max version requirement ..."
+
minC=$(get_comparable_java_version ${JVMVersion})
maxC=$(get_comparable_java_version ${JVMMaxVersion})
matchingJVMs=()
@@ -643,7 +775,7 @@ if [ -z "${JAVACMD}" ] || [ ! -x "${JAVACMD}" ] ; then
# debug output
for i in "${matchingJVMs[@]}"
do
- stub_logger "[JavaSearch] ... ... matches all requirements: $i"
+ stub_logger "[JavaSearch] ... matches all requirements: $i"
done
@@ -700,9 +832,10 @@ if [ -z "${JAVACMD}" ] || [ ! -x "${JAVACMD}" ] ; then
stub_logger "[EXIT 3] ${MSG_NO_SUITABLE_JAVA_EXPANDED}"
# display error message with AppleScript
- osascript -e "tell application \"System Events\" to display dialog \"${MSG_ERROR_LAUNCHING}\n\n${MSG_NO_SUITABLE_JAVA_EXPANDED}\n${MSG_NO_SUITABLE_JAVA_CHECK}\" with title \"${CFBundleName}\" buttons {\" OK \", \"${MSG_VISIT_JAVA_DOT_COM}\"} default button \"${MSG_VISIT_JAVA_DOT_COM}\" with icon path to resource \"${CFBundleIconFile}\" in bundle (path to me)" \
+ osascript -e "tell application \"System Events\" to display dialog \"${MSG_ERROR_LAUNCHING}\n\n${MSG_NO_SUITABLE_JAVA_EXPANDED}\n${MSG_NO_SUITABLE_JAVA_CHECK}\" with title \"${CFBundleName}\" buttons {\" OK \", \"${MSG_VISIT_JAVA_DOT_COM}\", \"${MSG_VISIT_ADOPTIUM}\"} default button 1${DialogWithIcon}" \
-e "set response to button returned of the result" \
- -e "if response is \"${MSG_VISIT_JAVA_DOT_COM}\" then open location \"http://java.com\""
+ -e "if response is \"${MSG_VISIT_JAVA_DOT_COM}\" then open location \"https://www.java.com/download/\"" \
+ -e "if response is \"${MSG_VISIT_ADOPTIUM}\" then open location \"https://adoptium.net/releases.html\""
# exit with error
exit 3
@@ -710,9 +843,10 @@ if [ -z "${JAVACMD}" ] || [ ! -x "${JAVACMD}" ] ; then
# log exit cause
stub_logger "[EXIT 1] ${MSG_ERROR_LAUNCHING}"
# display error message with AppleScript
- osascript -e "tell application \"System Events\" to display dialog \"${MSG_ERROR_LAUNCHING}\n\n${MSG_INSTALL_JAVA}\" with title \"${CFBundleName}\" buttons {\"${MSG_LATER}\", \"${MSG_VISIT_JAVA_DOT_COM}\"} default button \"${MSG_VISIT_JAVA_DOT_COM}\" with icon path to resource \"${CFBundleIconFile}\" in bundle (path to me)" \
+ osascript -e "tell application \"System Events\" to display dialog \"${MSG_ERROR_LAUNCHING}\n\n${MSG_INSTALL_JAVA}\" with title \"${CFBundleName}\" buttons {\"${MSG_LATER}\", \"${MSG_VISIT_JAVA_DOT_COM}\", \"${MSG_VISIT_ADOPTIUM}\"} default button 1${DialogWithIcon}" \
-e "set response to button returned of the result" \
- -e "if response is \"${MSG_VISIT_JAVA_DOT_COM}\" then open location \"http://java.com\""
+ -e "if response is \"${MSG_VISIT_JAVA_DOT_COM}\" then open location \"https://www.java.com/download/\"" \
+ -e "if response is \"${MSG_VISIT_ADOPTIUM}\" then open location \"https://adoptium.net/releases.html\""
# exit with error
exit 1
fi
@@ -727,7 +861,7 @@ if [ -z "${JVMMainClass}" ]; then
# log exit cause
stub_logger "[EXIT 2] ${MSG_MISSING_MAINCLASS}"
# display error message with AppleScript
- osascript -e "tell application \"System Events\" to display dialog \"${MSG_ERROR_LAUNCHING}\n\n${MSG_MISSING_MAINCLASS}\" with title \"${CFBundleName}\" buttons {\" OK \"} default button 1 with icon path to resource \"${CFBundleIconFile}\" in bundle (path to me)"
+ osascript -e "tell application \"System Events\" to display dialog \"${MSG_ERROR_LAUNCHING}\n\n${MSG_MISSING_MAINCLASS}\" with title \"${CFBundleName}\" buttons {\" OK \"} default button 1${DialogWithIcon}"
# exit with error
exit 2
fi
@@ -761,13 +895,13 @@ stub_logger "[WorkingDirectory] ${WorkingDirectory}"
# - main class
# - main class arguments
# - passthrough arguments from Terminal or Drag'n'Drop to Finder icon
-stub_logger "[Exec] \"$JAVACMD\" -cp \"${JVMClassPath}\" -splash:\"${ResourcesFolder}/${JVMSplashFile}\" -Xdock:icon=\"${ResourcesFolder}/${CFBundleIconFile}\" -Xdock:name=\"${CFBundleName}\" ${JVMOptionsArr:+$(printf "'%s' " "${JVMOptionsArr[@]}") }${JVMDefaultOptions:+$JVMDefaultOptions }${JVMMainClass}${MainArgsArr:+ $(printf "'%s' " "${MainArgsArr[@]}")}${ArgsPassthru:+ $(printf "'%s' " "${ArgsPassthru[@]}")}"
+stub_logger "[Exec] \"$JAVACMD\" -cp \"${JVMClassPath}\" ${JVMSplashFile:+ -splash:\"${ResourcesFolder}/${JVMSplashFile}\"} -Xdock:icon=\"${ResourcesFolder}/${CFBundleIconFile}\" -Xdock:name=\"${CFBundleName}\" ${JVMOptionsArr:+$(printf "'%s' " "${JVMOptionsArr[@]}") }${JVMDefaultOptions:+$JVMDefaultOptions }${JVMMainClass}${MainArgsArr:+ $(printf "'%s' " "${MainArgsArr[@]}")}${ArgsPassthru:+ $(printf "'%s' " "${ArgsPassthru[@]}")}"
exec "${JAVACMD}" \
-cp "${JVMClassPath}" \
- -splash:"${ResourcesFolder}/${JVMSplashFile}" \
+ ${JVMSplashFile:+ -splash:"${ResourcesFolder}/${JVMSplashFile}"} \
-Xdock:icon="${ResourcesFolder}/${CFBundleIconFile}" \
-Xdock:name="${CFBundleName}" \
- ${JVMOptions:+"${JVMOptions[@]}" }\
+ ${JVMOptionsArr:+"${JVMOptionsArr[@]}" }\
${JVMDefaultOptions:+$JVMDefaultOptions }\
"${JVMMainClass}"\
${MainArgsArr:+ "${MainArgsArr[@]}"}\
diff --git a/src/dr/app/beast/BeastVersion.java b/src/dr/app/beast/BeastVersion.java
index 82e4613f34..c74ef47379 100644
--- a/src/dr/app/beast/BeastVersion.java
+++ b/src/dr/app/beast/BeastVersion.java
@@ -55,12 +55,12 @@ public class BeastVersion implements Version, Citable {
*/
private static final String VERSION = "1.10.5";
- private static final String DATE_STRING = "2002-2019";
+ private static final String DATE_STRING = "2002-2023";
private static final boolean IS_PRERELEASE = true;
// this is now being manually updated since the move to GitHub. 7 digits of GitHub hash.
- private static final String REVISION = "23570d1";
+ private static final String REVISION = "8a10723";
public String getVersion() {
return VERSION;
diff --git a/src/dr/app/beast/development_parsers.properties b/src/dr/app/beast/development_parsers.properties
index 806771dbac..3d1250f629 100644
--- a/src/dr/app/beast/development_parsers.properties
+++ b/src/dr/app/beast/development_parsers.properties
@@ -374,3 +374,7 @@ dr.evomodelxml.SampleFromLogFilesParser
dr.evoxml.ReportSitePatternMapParser
+dr.evomodelxml.tree.TreeReportParser
+
+# Misc
+dr.inferencexml.loggers.TimeLoggerXMLParser
diff --git a/src/dr/app/beast/release_parsers.properties b/src/dr/app/beast/release_parsers.properties
index 30400abf63..18691aaf9c 100644
--- a/src/dr/app/beast/release_parsers.properties
+++ b/src/dr/app/beast/release_parsers.properties
@@ -287,6 +287,8 @@ dr.evomodelxml.tree.TreeLengthStatisticParser
dr.evomodelxml.tree.NodeHeightsStatisticParser
dr.evomodelxml.tree.TreeShapeStatisticParser
dr.evomodelxml.tree.TMRCAStatisticParser
+dr.evomodelxml.tree.BranchLengthStatisticParser
+dr.evomodelxml.tree.AgeStatisticParser
dr.evomodelxml.tree.MRCATraitStatisticParser
dr.evomodelxml.tree.AncestralTraitParser
dr.evomodelxml.tree.ExternalLengthStatisticParser
diff --git a/src/dr/app/beauti/BeautiFrame.java b/src/dr/app/beauti/BeautiFrame.java
index 05e581cd58..e3f7d138c7 100644
--- a/src/dr/app/beauti/BeautiFrame.java
+++ b/src/dr/app/beauti/BeautiFrame.java
@@ -509,25 +509,25 @@ private void importFiles(File[] files) {
// JOptionPane.showMessageDialog(this, "Unable to open file: File not found",
// "Unable to open file", JOptionPane.ERROR_MESSAGE);
} catch (IOException ioe) {
- JOptionPane.showMessageDialog(this, "File I/O Error unable to read file: " + ioe.getMessage(),
+ JOptionPane.showMessageDialog(this, "File I/O Error unable to read file:\n " + ioe.getMessage(),
"Unable to read file", JOptionPane.ERROR_MESSAGE);
ioe.printStackTrace();
// there may be other files in the list so don't return
// return;
} catch (MissingBlockException ex) {
- JOptionPane.showMessageDialog(this, "TAXON, DATA or CHARACTERS block is missing in Nexus file: " + ex,
+ JOptionPane.showMessageDialog(this, "TAXON, DATA or CHARACTERS block is missing in Nexus file:\n " + ex.getMessage(),
"Missing Block in Nexus File",
JOptionPane.ERROR_MESSAGE);
ex.printStackTrace();
} catch (ImportException ime) {
- JOptionPane.showMessageDialog(this, "Error parsing imported file: " + ime,
+ JOptionPane.showMessageDialog(this, "Error parsing imported file:\n " + ime.getMessage(),
"Error reading file",
JOptionPane.ERROR_MESSAGE);
ime.printStackTrace();
} catch (JDOMException jde) {
- JOptionPane.showMessageDialog(this, "Error parsing imported file: " + jde,
+ JOptionPane.showMessageDialog(this, "Error parsing imported file:\n " + jde.getMessage(),
"Error reading file",
JOptionPane.ERROR_MESSAGE);
jde.printStackTrace();
diff --git a/src/dr/app/beauti/components/marginalLikelihoodEstimation/MarginalLikelihoodEstimationGenerator.java b/src/dr/app/beauti/components/marginalLikelihoodEstimation/MarginalLikelihoodEstimationGenerator.java
index 572e4628c0..9d997ecb0e 100644
--- a/src/dr/app/beauti/components/marginalLikelihoodEstimation/MarginalLikelihoodEstimationGenerator.java
+++ b/src/dr/app/beauti/components/marginalLikelihoodEstimation/MarginalLikelihoodEstimationGenerator.java
@@ -993,7 +993,7 @@ public void writeMLE(XMLWriter writer, MarginalLikelihoodEstimationOptions optio
new Attribute.Default(PriorParsers.MEAN, "" + Math.log(2)),
new Attribute.Default(PriorParsers.OFFSET, "" + 0.0)
});
- writer.writeIDref("statistic", model.getPrefix() + ClockType.LOCAL_CLOCK + ".changes");
+ writer.writeIDref("statistic", model.getPrefix() + "rateChanges");
writer.writeCloseTag(PriorParsers.POISSON_PRIOR);
writer.writeOpenTag(PriorParsers.GAMMA_PRIOR,
diff --git a/src/dr/app/beauti/generator/OperatorsGenerator.java b/src/dr/app/beauti/generator/OperatorsGenerator.java
index 74b551a777..b4dd45ad5a 100644
--- a/src/dr/app/beauti/generator/OperatorsGenerator.java
+++ b/src/dr/app/beauti/generator/OperatorsGenerator.java
@@ -36,13 +36,17 @@
import dr.evomodelxml.coalescent.operators.GMRFSkyrideBlockUpdateOperatorParser;
import dr.evomodelxml.coalescent.operators.SampleNonActiveGibbsOperatorParser;
import dr.evomodelxml.operators.*;
+import dr.inference.model.CompoundParameter;
import dr.inference.model.ParameterParser;
import dr.inference.operators.AdaptableVarianceMultivariateNormalOperator;
import dr.inference.operators.OperatorSchedule;
import dr.inference.operators.RandomWalkOperator;
import dr.inference.operators.RateBitExchangeOperator;
+import dr.inferencexml.SignTransformParser;
+import dr.inferencexml.hmc.CompoundGradientParser;
import dr.inferencexml.model.CompoundParameterParser;
import dr.inferencexml.operators.*;
+import dr.inferencexml.operators.hmc.HamiltonianMonteCarloOperatorParser;
import dr.oldevomodel.substmodel.AbstractSubstitutionModel;
import dr.oldevomodelxml.substmodel.GeneralSubstitutionModelParser;
import dr.util.Attribute;
@@ -218,6 +222,9 @@ private void writeOperator(Operator operator, XMLWriter writer) {
case SKY_GRID_GIBBS_OPERATOR:
writeSkyGridGibbsOperator(operator, prefix, writer);
break;
+ case SKY_GRID_HMC_OPERATOR:
+ writeSkyGridHMCOperator(operator, prefix, writer);
+ break;
case ADAPTIVE_MULTIVARIATE:
writeAdaptiveMultivariateOperator(operator, writer);
break;
@@ -497,6 +504,34 @@ private void writeSkyGridGibbsOperator(Operator operator, String treePriorPrefix
writer.writeCloseTag(GMRFSkyrideBlockUpdateOperatorParser.GRID_BLOCK_UPDATE_OPERATOR);
}
+ private void writeSkyGridHMCOperator(Operator operator, String treePriorPrefix, XMLWriter writer) {
+ writer.writeOpenTag(
+ HamiltonianMonteCarloOperatorParser.HMC_OPERATOR,
+ new Attribute[]{
+ getWeightAttribute(operator.getWeight()),
+ new Attribute.Default(HamiltonianMonteCarloOperatorParser.N_STEPS, 50),
+ new Attribute.Default(HamiltonianMonteCarloOperatorParser.STEP_SIZE, 1E-2),
+ new Attribute.Default(HamiltonianMonteCarloOperatorParser.MODE, "vanilla"),
+ new Attribute.Default(HamiltonianMonteCarloOperatorParser.GRADIENT_CHECK_COUNT, 0),
+ new Attribute.Default(HamiltonianMonteCarloOperatorParser.GRADIENT_CHECK_TOLERANCE, 1E-1),
+ new Attribute.Default(HamiltonianMonteCarloOperatorParser.PRECONDITIONING, "none"),
+ new Attribute.Default(HamiltonianMonteCarloOperatorParser.PRECONDITIONING_UPDATE_FREQUENCY, 100)
+ }
+ );
+ writer.writeIDref(CompoundGradientParser.SUM_DERIVATIVE2, treePriorPrefix + "full.skygrid.gradient");
+ writer.writeIDref(CompoundParameterParser.COMPOUND_PARAMETER, treePriorPrefix + "skygrid.parameters");
+ writer.writeOpenTag(
+ SignTransformParser.NAME,
+ new Attribute[]{
+ new Attribute.Default(TransformParsers.START, 1),
+ new Attribute.Default(TransformParsers.END, 1)
+ }
+ );
+ writer.writeIDref(CompoundParameterParser.COMPOUND_PARAMETER, treePriorPrefix + "skygrid.parameters");
+ writer.writeCloseTag(SignTransformParser.NAME);
+ writer.writeCloseTag(HamiltonianMonteCarloOperatorParser.HMC_OPERATOR);
+ }
+
private void writeGMRFGibbsOperator(Operator operator, String treePriorPrefix, XMLWriter writer) {
writer.writeOpenTag(
GMRFSkyrideBlockUpdateOperatorParser.BLOCK_UPDATE_OPERATOR,
diff --git a/src/dr/app/beauti/generator/ParameterPriorGenerator.java b/src/dr/app/beauti/generator/ParameterPriorGenerator.java
index 2e3fe0cd4c..3602f555f7 100644
--- a/src/dr/app/beauti/generator/ParameterPriorGenerator.java
+++ b/src/dr/app/beauti/generator/ParameterPriorGenerator.java
@@ -32,7 +32,6 @@
import dr.app.beauti.util.XMLWriter;
import dr.evolution.util.Taxa;
import dr.evomodel.tree.DefaultTreeModel;
-import dr.evomodel.tree.TreeModel;
import dr.evomodelxml.tree.CTMCScalePriorParser;
import dr.evomodelxml.tree.MonophylyStatisticParser;
import dr.inference.model.ParameterParser;
@@ -41,6 +40,7 @@
import dr.inferencexml.model.OneOnXPriorParser;
import dr.util.Attribute;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -51,8 +51,14 @@
*/
public class ParameterPriorGenerator extends Generator {
+ //map parameters to prior IDs, for use with HMC
+ private HashMap mapParameterToPrior;
+
public ParameterPriorGenerator(BeautiOptions options, ComponentFactory[] components) {
super(options, components);
+ //TODO don't like this being here, but will see how things pan out as more HMC approaches are added
+ mapParameterToPrior = new HashMap();
+ mapParameterToPrior.put("skygrid.precision", "skygrid.precision.prior");
}
/**
@@ -63,7 +69,6 @@ public ParameterPriorGenerator(BeautiOptions options, ComponentFactory[] compone
public void writeParameterPriors(XMLWriter writer) {
boolean first = true;
-
for (Map.Entry taxaBooleanEntry : options.taxonSetsMono.entrySet()) {
if (taxaBooleanEntry.getValue()) {
if (first) {
@@ -80,7 +85,6 @@ public void writeParameterPriors(XMLWriter writer) {
List parameters = options.selectParameters();
-
for (Parameter parameter : parameters) {
if (!(parameter.priorType == PriorType.NONE_TREE_PRIOR ||
parameter.priorType == PriorType.NONE_FIXED ||
@@ -112,6 +116,18 @@ private void writeCachedParameterPrior(Parameter parameter, XMLWriter writer) {
* @param writer the writer
*/
public void writeParameterPrior(Parameter parameter, XMLWriter writer) {
+
+ //if models need to have a prior defined before the priors block
+ /*if (reservedParameters.contains(parameter.getName())) {
+
+ return;
+ }*/
+
+ if (mapParameterToPrior.keySet().contains(parameter.getName())) {
+ writePriorIdref(writer, parameter, mapParameterToPrior.get(parameter.getName()));
+ return;
+ }
+
if (parameter.priorType == PriorType.NONE_FIXED) {
return;
}
@@ -349,4 +365,23 @@ private void writeParameterIdref(XMLWriter writer, Parameter parameter) {
}
}
+ private void writePriorIdref(XMLWriter writer, Parameter parameter, String priorID) {
+ switch (parameter.priorType) {
+ case GAMMA_PRIOR:
+ writer.writeIDref(PriorParsers.GAMMA_PRIOR, priorID);
+ break;
+ case LOGNORMAL_PRIOR:
+ writer.writeIDref(PriorParsers.LOG_NORMAL_PRIOR, priorID);
+ break;
+ case EXPONENTIAL_PRIOR:
+ writer.writeIDref(PriorParsers.EXPONENTIAL_PRIOR, priorID);
+ break;
+ case INVERSE_GAMMA_PRIOR:
+ writer.writeIDref(PriorParsers.INVGAMMA_PRIOR_CORRECT, priorID);
+ break;
+ default:
+ throw new IllegalArgumentException("Unknown or invalid prior defined on " + parameter.getName());
+ }
+ }
+
}
diff --git a/src/dr/app/beauti/generator/TreePriorGenerator.java b/src/dr/app/beauti/generator/TreePriorGenerator.java
index 571ec569ce..87e7c4810c 100644
--- a/src/dr/app/beauti/generator/TreePriorGenerator.java
+++ b/src/dr/app/beauti/generator/TreePriorGenerator.java
@@ -27,12 +27,14 @@
import dr.app.beauti.components.ComponentFactory;
import dr.app.beauti.options.*;
+import dr.app.beauti.types.OperatorSetType;
import dr.app.beauti.types.StartingTreeType;
import dr.app.beauti.types.TreePriorParameterizationType;
import dr.app.beauti.types.TreePriorType;
import dr.app.beauti.util.XMLWriter;
import dr.evolution.util.Taxa;
import dr.evolution.util.Units;
+import dr.evomodel.coalescent.GMRFSkyrideGradient;
import dr.evomodel.tree.DefaultTreeModel;
import dr.evomodel.tree.TreeModel;
import dr.evomodelxml.CSVExporterParser;
@@ -45,11 +47,16 @@
import dr.evoxml.TaxaParser;
import dr.inference.distribution.ExponentialDistributionModel;
import dr.inference.distribution.ExponentialMarkovModel;
+import dr.inference.distribution.GammaDistributionModel;
+import dr.inference.model.CompoundParameter;
import dr.inference.model.ParameterParser;
-import dr.inferencexml.distribution.DistributionModelParser;
-import dr.inferencexml.distribution.ExponentialMarkovModelParser;
-import dr.inferencexml.distribution.MixedDistributionLikelihoodParser;
+import dr.inferencexml.distribution.*;
+import dr.inferencexml.hmc.CompoundGradientParser;
+import dr.inferencexml.hmc.GradientWrapperParser;
+import dr.inferencexml.hmc.JointGradientParser;
+import dr.inferencexml.model.CompoundParameterParser;
import dr.inferencexml.model.SumStatisticParser;
+import dr.math.distributions.GammaDistribution;
import dr.util.Attribute;
import dr.xml.XMLParser;
@@ -728,6 +735,72 @@ void writeMultiLociTreePriors(PartitionTreePrior prior, XMLWriter writer) {
writer.writeCloseTag(GMRFSkyrideLikelihoodParser.SKYGRID_LIKELIHOOD);
+ //writing the gamma prior here so will need to prevent another one from being written in the priors block
+ //key use: using HMC on the skygrid parameters
+ writer.writeOpenTag(PriorParsers.GAMMA_PRIOR,
+ new Attribute[]{
+ new Attribute.Default(XMLParser.ID, "skygrid.precision.prior"),
+ new Attribute.Default(GammaDistributionModelParser.SHAPE, 0.001),
+ new Attribute.Default(GammaDistributionModelParser.SCALE, 1000.0),
+ new Attribute.Default(GammaDistributionModelParser.OFFSET, 0.0)
+ }
+ );
+ writer.writeIDref(ParameterParser.PARAMETER, "skygrid.precision");
+ writer.writeCloseTag(PriorParsers.GAMMA_PRIOR);
+
+ //add gradient information to XML file in case of an HMC transition kernel mix
+ if (options.operatorSetType == OperatorSetType.HMC) {
+
+ writer.writeOpenTag(GMRFSkyrideGradientParser.NAME,
+ new Attribute[]{
+ new Attribute.Default(XMLParser.ID, "gmrfGradientPop"),
+ new Attribute.Default(GMRFSkyrideGradientParser.WRT_PARAMETER, "logPopulationSizes")
+ }
+ );
+ writer.writeIDref(GMRFSkyrideLikelihoodParser.SKYGRID_LIKELIHOOD, "skygrid");
+ writer.writeCloseTag(GMRFSkyrideGradientParser.NAME);
+
+ writer.writeOpenTag(CompoundParameterParser.COMPOUND_PARAMETER,
+ new Attribute[]{
+ new Attribute.Default(XMLParser.ID, "skygrid.parameters")
+ }
+ );
+ writer.writeIDref(ParameterParser.PARAMETER, "skygrid.precision");
+ writer.writeIDref(ParameterParser.PARAMETER, "skygrid.logPopSize");
+ writer.writeCloseTag(CompoundParameterParser.COMPOUND_PARAMETER);
+
+ writer.writeOpenTag(GMRFSkyrideGradientParser.NAME,
+ new Attribute[]{
+ new Attribute.Default(XMLParser.ID, "gmrfGradientPrec"),
+ new Attribute.Default(GMRFSkyrideGradientParser.WRT_PARAMETER, "precision")
+ }
+ );
+ writer.writeIDref(GMRFSkyrideLikelihoodParser.SKYGRID_LIKELIHOOD, "skygrid");
+ writer.writeCloseTag(GMRFSkyrideGradientParser.NAME);
+
+ writer.writeOpenTag(JointGradientParser.SUM_DERIVATIVE2,
+ new Attribute[]{
+ new Attribute.Default(XMLParser.ID, "joint.skygrid.precision")
+ }
+ );
+ writer.writeIDref(GMRFSkyrideGradientParser.NAME, "gmrfGradientPrec");
+ writer.writeOpenTag(GradientWrapperParser.NAME);
+ writer.writeIDref(PriorParsers.GAMMA_PRIOR, "skygrid.precision.prior");
+ writer.writeIDref(ParameterParser.PARAMETER, "skygrid.precision");
+ writer.writeCloseTag(GradientWrapperParser.NAME);
+ writer.writeCloseTag(JointGradientParser.SUM_DERIVATIVE2);
+
+ writer.writeOpenTag(CompoundGradientParser.SUM_DERIVATIVE2,
+ new Attribute[]{
+ new Attribute.Default(XMLParser.ID, "full.skygrid.gradient")
+ }
+ );
+ writer.writeIDref(JointGradientParser.SUM_DERIVATIVE2, "joint.skygrid.precision");
+ writer.writeIDref(GMRFSkyrideGradientParser.NAME, "gmrfGradientPop");
+ writer.writeCloseTag(CompoundGradientParser.SUM_DERIVATIVE2);
+
+ }
+
} else if (prior.getNodeHeightPrior() == TreePriorType.EXTENDED_SKYLINE) {
final String tagName = VariableDemographicModelParser.MODEL_NAME;
diff --git a/src/dr/app/beauti/operatorspanel/OperatorsPanel.java b/src/dr/app/beauti/operatorspanel/OperatorsPanel.java
index 44efaeb6a0..12ac35d0c3 100644
--- a/src/dr/app/beauti/operatorspanel/OperatorsPanel.java
+++ b/src/dr/app/beauti/operatorspanel/OperatorsPanel.java
@@ -66,7 +66,8 @@ public class OperatorsPanel extends BeautiPanel implements Exportable {
OperatorSetType.FIXED_TREE_TOPOLOGY,
OperatorSetType.NEW_TREE_MIX,
OperatorSetType.ADAPTIVE_MULTIVARIATE,
- OperatorSetType.CUSTOM
+ OperatorSetType.CUSTOM,
+ OperatorSetType.HMC
});
public List operators = new ArrayList();
diff --git a/src/dr/app/beauti/options/ModelOptions.java b/src/dr/app/beauti/options/ModelOptions.java
index e0bd1d9525..98c9aa2cc7 100644
--- a/src/dr/app/beauti/options/ModelOptions.java
+++ b/src/dr/app/beauti/options/ModelOptions.java
@@ -137,6 +137,9 @@ public Parameter createParameterUniformPrior(String name, String description, Pr
.initial(initial).uniformLower(uniformLower).uniformUpper(uniformUpper).build(parameters);
}
+ //TODO think about having a createParameter method with a String priorID argument
+ //public Parameter createParameterGammaPrior(String name, String priorID, String description, ...) {
+
public Parameter createParameterGammaPrior(String name, String description, PriorScaleType scaleType, double initial,
double shape, double scale, boolean priorFixed) {
return createParameterGammaPrior(name, description, scaleType, initial, shape, scale, priorFixed, false);
diff --git a/src/dr/app/beauti/options/Parameter.java b/src/dr/app/beauti/options/Parameter.java
index 47a6f4a737..42efb411d3 100644
--- a/src/dr/app/beauti/options/Parameter.java
+++ b/src/dr/app/beauti/options/Parameter.java
@@ -49,10 +49,13 @@ public class Parameter implements Serializable {
private boolean meanInRealSpace = false;
- // Required para
+ // Required parameters
private String baseName;
private final String description;
+ //TODO think about have an optional (could be public) parameter priorID to idref to the prior later on
+ //private String priorID;
+
private int dimensionWeight = 1;
private final List subParameters = new ArrayList();
diff --git a/src/dr/app/beauti/options/PartitionTreeModel.java b/src/dr/app/beauti/options/PartitionTreeModel.java
index c5d9df77b2..26e8ea1cfd 100644
--- a/src/dr/app/beauti/options/PartitionTreeModel.java
+++ b/src/dr/app/beauti/options/PartitionTreeModel.java
@@ -173,6 +173,7 @@ public List selectOperators(List operators) {
boolean branchesInUse = false;
boolean newTreeOperatorsInUse = false;
boolean adaptiveMultivariateInUse = false;
+ boolean HMCinUse = false;
// if not a fixed tree then sample tree space
if (options.operatorSetType == OperatorSetType.DEFAULT) {
@@ -185,6 +186,8 @@ public List selectOperators(List operators) {
} else if (options.operatorSetType == OperatorSetType.ADAPTIVE_MULTIVARIATE) {
newTreeOperatorsInUse = true;
adaptiveMultivariateInUse = true;
+ } else if (options.operatorSetType == OperatorSetType.HMC) {
+ HMCinUse = true;
} else {
throw new IllegalArgumentException("Unknown operator set type");
}
@@ -199,6 +202,7 @@ public List selectOperators(List operators) {
getOperator("subtreeLeap").setUsed(newTreeOperatorsInUse);
getOperator("FHSPR").setUsed(newTreeOperatorsInUse);
+
}
return operators;
}
diff --git a/src/dr/app/beauti/options/PartitionTreePrior.java b/src/dr/app/beauti/options/PartitionTreePrior.java
index 5facb872dd..65261a61ce 100644
--- a/src/dr/app/beauti/options/PartitionTreePrior.java
+++ b/src/dr/app/beauti/options/PartitionTreePrior.java
@@ -271,9 +271,11 @@ public void initModelParametersAndOpererators() {
"demographic.indicators", OperatorType.SCALE_WITH_INDICATORS, 0.5, 2 * demoWeights);
createOperatorUsing2Parameters("gmrfGibbsOperator", "gmrfGibbsOperator", "Gibbs sampler for GMRF Skyride", "skyride.logPopSize",
"skyride.precision", OperatorType.GMRF_GIBBS_OPERATOR, 2, 2);
- createOperatorUsing2Parameters("gmrfSkyGridGibbsOperator", "gmrfGibbsOperator", "Gibbs sampler for Bayesian SkyGrid", "skygrid.logPopSize",
+ createOperatorUsing2Parameters("gmrfSkyGridGibbsOperator", "skygrid.logPopSize", "Gibbs sampler for Bayesian SkyGrid", "skygrid.logPopSize",
"skygrid.precision", OperatorType.SKY_GRID_GIBBS_OPERATOR, 1.0, 2);
- createScaleOperator("skygrid.precision", "description", 0.75, 1.0);
+ createScaleOperator("skygrid.precision", "skygrid precision", 0.75, 1.0);
+ createOperatorUsing2Parameters("gmrfSkyGridHMCOperator", "Multiple", "HMC transition kernel for Bayesian SkyGrid", "skygrid.logPopSize",
+ "skygrid.precision", OperatorType.SKY_GRID_HMC_OPERATOR, 1.0, 2);
createScaleOperator("yule.birthRate", demoTuning, demoWeights);
@@ -341,10 +343,10 @@ public List selectParameters(List params) {
params.add(getParameter("demographic.populationSizeChanges"));
params.add(getParameter("demographic.populationMean"));
} else if (nodeHeightPrior == TreePriorType.GMRF_SKYRIDE) {
-// params.add(getParameter("skyride.popSize")); // force user to use GMRF, not allowed to change
+ // params.add(getParameter("skyride.popSize")); // force user to use GMRF prior, not allowed to change
params.add(getParameter("skyride.precision"));
} else if (nodeHeightPrior == TreePriorType.SKYGRID) {
-// params.add(getParameter("skyride.popSize")); // force user to use GMRF, not allowed to change
+ // params.add(getParameter("skygrid.logPopSize")); // force user to use GMRF prior, not allowed to change
params.add(getParameter("skygrid.precision"));
} else if (nodeHeightPrior == TreePriorType.YULE || nodeHeightPrior == TreePriorType.YULE_CALIBRATION) {
params.add(getParameter("yule.birthRate"));
@@ -414,8 +416,12 @@ public List selectOperators(List ops) {
} else if (nodeHeightPrior == TreePriorType.GMRF_SKYRIDE) {
ops.add(getOperator("gmrfGibbsOperator"));
} else if (nodeHeightPrior == TreePriorType.SKYGRID) {
- ops.add(getOperator("gmrfSkyGridGibbsOperator"));
- ops.add(getOperator("skygrid.precision"));
+ if (options.operatorSetType == OperatorSetType.HMC) {
+ ops.add(getOperator("gmrfSkyGridHMCOperator"));
+ } else {
+ ops.add(getOperator("gmrfSkyGridGibbsOperator"));
+ ops.add(getOperator("skygrid.precision"));
+ }
} else if (nodeHeightPrior == TreePriorType.EXTENDED_SKYLINE) {
ops.add(getOperator("demographic.populationMean"));
ops.add(getOperator("demographic.popSize"));
diff --git a/src/dr/app/beauti/types/OperatorSetType.java b/src/dr/app/beauti/types/OperatorSetType.java
index 9b09683ba1..6ddf6fac82 100644
--- a/src/dr/app/beauti/types/OperatorSetType.java
+++ b/src/dr/app/beauti/types/OperatorSetType.java
@@ -34,7 +34,8 @@ public enum OperatorSetType {
FIXED_TREE_TOPOLOGY("fixed tree topology"),
NEW_TREE_MIX("new tree operator mix"),
ADAPTIVE_MULTIVARIATE("adaptive multivariate"),
- CUSTOM("custom operator mix");
+ CUSTOM("custom operator mix"),
+ HMC("Hamiltonian Monte Carlo");
OperatorSetType(String displayName) {
this.displayName = displayName;
diff --git a/src/dr/app/beauti/types/OperatorType.java b/src/dr/app/beauti/types/OperatorType.java
index c9455f3657..70df357186 100644
--- a/src/dr/app/beauti/types/OperatorType.java
+++ b/src/dr/app/beauti/types/OperatorType.java
@@ -66,6 +66,7 @@ public enum OperatorType {
WIDE_EXCHANGE("wideExchange"),
GMRF_GIBBS_OPERATOR("gmrfGibbsOperator"),
SKY_GRID_GIBBS_OPERATOR("gmrfGibbsOperator"),
+ SKY_GRID_HMC_OPERATOR("gmrfHMCOperator"),
// PRECISION_GMRF_OPERATOR("precisionGMRFOperator"),
WILSON_BALDING("wilsonBalding");
diff --git a/src/dr/app/beauti/util/BEAUTiImporter.java b/src/dr/app/beauti/util/BEAUTiImporter.java
index 3e6e362eff..f6d9062a38 100644
--- a/src/dr/app/beauti/util/BEAUTiImporter.java
+++ b/src/dr/app/beauti/util/BEAUTiImporter.java
@@ -41,6 +41,7 @@
import dr.evolution.io.NexusImporter;
import dr.evolution.io.NexusImporter.MissingBlockException;
import dr.evolution.io.NexusImporter.NexusBlock;
+import dr.evolution.sequence.Sequence;
import dr.evolution.tree.Tree;
import dr.evolution.util.Taxa;
import dr.evolution.util.Taxon;
@@ -560,6 +561,18 @@ private void setData(String fileName, TaxonList taxonList, Alignment alignment,
options.fileNameStem = fileNameStem;
}
+ // check the alignment before adding it...
+ if (alignment.getSiteCount() == 0) {
+ // sequences are different lengths
+ throw new ImportException("This alignment is of zero length");
+ }
+ for (Sequence seq : alignment.getSequences()) {
+ if (seq.getLength() != alignment.getSiteCount()) {
+ // sequences are different lengths
+ throw new ImportException("The sequences in the alignment file are of different lengths - BEAST requires aligned sequences");
+ }
+ }
+
addTaxonList(taxonList);
addAlignment(alignment, charSets, model, fileName, fileNameStem);
diff --git a/src/dr/app/checkpoint/BeastCheckpointer.java b/src/dr/app/checkpoint/BeastCheckpointer.java
index b00264f180..fa1a0f8d86 100644
--- a/src/dr/app/checkpoint/BeastCheckpointer.java
+++ b/src/dr/app/checkpoint/BeastCheckpointer.java
@@ -533,6 +533,10 @@ protected long readStateFromFile(File file, MarkovChain markovChain, double[] ln
}
System.out.println();
}
+ } else {
+ if (DEBUG) {
+ System.out.println("Not a TreeModel: " + model.getModelName());
+ }
}
//first add all TreeParameterModels to a list
@@ -541,6 +545,9 @@ protected long readStateFromFile(File file, MarkovChain markovChain, double[] ln
System.out.println("\nLoad TreeParameterModel: " + model.getClass().getSimpleName());
}
traitModels.add((TreeParameterModel)model);
+ if (DEBUG) {
+ System.out.println("TreeParameterModel: " + model.getModelName());
+ }
}
}
@@ -598,6 +605,9 @@ protected long readStateFromFile(File file, MarkovChain markovChain, double[] ln
int edgeCount = Integer.parseInt(fields[0]);
if (DEBUG) {
System.out.println("edge count = " + edgeCount);
+ System.out.println("model: " + model.getId());
+ System.out.println("linkedModels size = " + linkedModels.size());
+ System.out.println(linkedModels.get(model.getId()));
}
//create data matrix of doubles to store information from list of TreeParameterModels
@@ -670,7 +680,7 @@ protected long readStateFromFile(File file, MarkovChain markovChain, double[] ln
if (DEBUG) {
System.out.println("\nDouble checking:");
for (Parameter parameter : Parameter.CONNECTED_PARAMETER_SET) {
- if (parameter.getParameterName().equals("branchRates.categories.rootNodeNumber")) {
+ if (parameter.getParameterName() != null && parameter.getParameterName().equals("branchRates.categories.rootNodeNumber")) {
System.out.println(parameter.getParameterName() + ": " + parameter.getParameterValue(0));
}
}
diff --git a/src/dr/app/tools/TreeAnnotator.java b/src/dr/app/tools/TreeAnnotator.java
index bdf767d386..5f3c9e3482 100644
--- a/src/dr/app/tools/TreeAnnotator.java
+++ b/src/dr/app/tools/TreeAnnotator.java
@@ -72,7 +72,7 @@ public class TreeAnnotator {
enum Target {
MAX_CLADE_CREDIBILITY("Maximum clade credibility tree"),
- MAX_MARGINAL_CLADE_CREDIBILITY("Maximum marginal clade credibilities"),
+ HIPSTR("Highest independent posterior subtree reconstruction (HIPSTR)"),
USER_TARGET_TREE("User target tree");
String desc;
@@ -267,9 +267,9 @@ public TreeAnnotator(final int burninTrees,
targetTree = new FlexibleTree(getMCCTree(burnin, cladeSystem, inputFileName));
break;
}
- case MAX_MARGINAL_CLADE_CREDIBILITY: {
- progressStream.println("Finding maximum marginal credibility tree...");
- targetTree = new FlexibleTree(getMMCCTree(cladeSystem));
+ case HIPSTR: {
+ progressStream.println("Finding highest independent posterior subtree reconstruction (HIPSTR) tree...");
+ targetTree = new FlexibleTree(getHIPSTRTree(cladeSystem));
break;
}
default: throw new IllegalArgumentException("Unknown targetOption");
@@ -416,15 +416,15 @@ private Tree getMCCTree(int burnin, CladeSystem cladeSystem, String inputFileNam
return bestTree;
}
- private Tree getMMCCTree(CladeSystem cladeSystem) {
+ private Tree getHIPSTRTree(CladeSystem cladeSystem) {
CladeSystem.Clade rootClade = cladeSystem.getRootClade();
credibilityCache.clear();
- double score = findMMCCTree(cladeSystem, rootClade);
+ double score = findHIPSTRTree(cladeSystem, rootClade);
- SimpleTree tree = new SimpleTree(buildMCCTree(cladeSystem, rootClade));
+ SimpleTree tree = new SimpleTree(buildHIPSTRTree(cladeSystem, rootClade));
progressStream.println();
progressStream.println("Highest Log Marginal Clade Credibility: " + score);
@@ -435,7 +435,7 @@ private Tree getMMCCTree(CladeSystem cladeSystem) {
private Map credibilityCache = new HashMap<>();
- private double findMMCCTree(CladeSystem cladeSystem, CladeSystem.Clade clade) {
+ private double findHIPSTRTree(CladeSystem cladeSystem, CladeSystem.Clade clade) {
double logCredibility = Math.log(clade.credibility);
@@ -451,7 +451,7 @@ private double findMMCCTree(CladeSystem cladeSystem, CladeSystem.Clade clade) {
double leftLogCredibility = credibilityCache.getOrDefault(left, Double.NaN);
if (Double.isNaN(leftLogCredibility)) {
- leftLogCredibility = findMMCCTree(cladeSystem, left);
+ leftLogCredibility = findHIPSTRTree(cladeSystem, left);
credibilityCache.put(left, leftLogCredibility);
}
CladeSystem.Clade right = cladeSystem.getCladeMap().get(subClade.snd);
@@ -460,7 +460,7 @@ private double findMMCCTree(CladeSystem cladeSystem, CladeSystem.Clade clade) {
}
double rightLogCredibility = credibilityCache.getOrDefault(right, Double.NaN);
if (Double.isNaN(rightLogCredibility)) {
- rightLogCredibility = findMMCCTree(cladeSystem, right);
+ rightLogCredibility = findHIPSTRTree(cladeSystem, right);
credibilityCache.put(right, rightLogCredibility);
}
@@ -479,13 +479,13 @@ private double findMMCCTree(CladeSystem cladeSystem, CladeSystem.Clade clade) {
return logCredibility;
}
- private SimpleNode buildMCCTree(CladeSystem cladeSystem, CladeSystem.Clade clade) {
+ private SimpleNode buildHIPSTRTree(CladeSystem cladeSystem, CladeSystem.Clade clade) {
SimpleNode newNode = new SimpleNode();
if (clade.size == 1) {
newNode.setTaxon(clade.taxon);
} else {
- newNode.addChild(buildMCCTree(cladeSystem, clade.bestLeft));
- newNode.addChild(buildMCCTree(cladeSystem, clade.bestRight));
+ newNode.addChild(buildHIPSTRTree(cladeSystem, clade.bestLeft));
+ newNode.addChild(buildHIPSTRTree(cladeSystem, clade.bestRight));
}
return newNode;
}
@@ -1551,7 +1551,7 @@ public static void main(String[] args) throws IOException {
Arguments arguments = new Arguments(
new Arguments.Option[]{
- new Arguments.StringOption("type", new String[] { "mcc", "mmcc" }, false, "an option of 'mcc' or 'mmcc'"),
+ new Arguments.StringOption("type", new String[] { "mcc", "hipstr" }, false, "an option of 'mcc' or 'hipstr'"),
new Arguments.StringOption("heights", new String[]{"keep", "median", "mean", "ca"}, false,
"an option of 'keep', 'median', 'mean' or 'ca' (default)"),
new Arguments.LongOption("burnin", "the number of states to be considered as 'burn-in'"),
@@ -1630,8 +1630,8 @@ public static void main(String[] args) throws IOException {
}
Target target = Target.MAX_CLADE_CREDIBILITY;
- if (arguments.hasOption("type") && arguments.getStringOption("type").equalsIgnoreCase("MMCC")) {
- target = Target.MAX_MARGINAL_CLADE_CREDIBILITY;
+ if (arguments.hasOption("type") && arguments.getStringOption("type").equalsIgnoreCase("HIPSTR")) {
+ target = Target.HIPSTR;
}
if (arguments.hasOption("target")) {
diff --git a/src/dr/app/treestat/CharactersPanel.java b/src/dr/app/treestat/CharactersPanel.java
index f2481ad486..7351797ea9 100644
--- a/src/dr/app/treestat/CharactersPanel.java
+++ b/src/dr/app/treestat/CharactersPanel.java
@@ -34,6 +34,7 @@
import java.util.ArrayList;
import dr.app.gui.table.TableSorter;
+import dr.evolution.util.Taxon;
import jam.table.TableRenderer;
import jam.framework.Exportable;
@@ -408,7 +409,10 @@ public void actionPerformed(ActionEvent ae) {
int saved1 = charactersTable.getSelectedRow();
int saved2 = statesTable.getSelectedRow();
int[] rows = excludedTaxaTable.getSelectedRows();
- ArrayList exclList = new ArrayList(treeStatData.allTaxa);
+ ArrayList exclList = new ArrayList<>();
+ for (Taxon taxon : treeStatData.allTaxa) {
+ exclList.add(taxon.getId());
+ }
exclList.removeAll(selectedState.taxa);
for (int row : rows) {
selectedState.taxa.add(exclList.get(row));
@@ -556,7 +560,10 @@ public Object getValueAt(int row, int col) {
if (included) {
return selectedState.taxa.get(row);
} else {
- ArrayList exclList = new ArrayList(treeStatData.allTaxa);
+ ArrayList exclList = new ArrayList<>();
+ for (Taxon taxon : treeStatData.allTaxa) {
+ exclList.add(taxon.getId());
+ }
exclList.removeAll(selectedState.taxa);
return exclList.get(row);
}
diff --git a/src/dr/app/treestat/StatisticsPanel.java b/src/dr/app/treestat/StatisticsPanel.java
index b421f7f0a0..4a80eb508d 100644
--- a/src/dr/app/treestat/StatisticsPanel.java
+++ b/src/dr/app/treestat/StatisticsPanel.java
@@ -326,7 +326,7 @@ public TreeSummaryStatistic createStatistic(TreeSummaryStatistic.Factory factory
if (factory.allowsTaxonList()) {
- for (Object taxonSet : treeStatData.taxonSets) {
+ for (Object taxonSet : treeStatData.taxonSets.values()) {
taxonSetCombo.addItem(taxonSet);
}
@@ -413,9 +413,7 @@ public void itemStateChanged(ItemEvent e) {
taxa.setId(t.name);
//Iterator iter = t.taxa.iterator();
for (Object aTaxa : t.taxa) {
- String id = (String) aTaxa;
- Taxon taxon = new Taxon(id);
- taxa.addTaxon(taxon);
+ taxa.addTaxon((Taxon) aTaxa);
}
statistic.setTaxonList(taxa);
} else {
diff --git a/src/dr/app/treestat/TaxonSetsPanel.java b/src/dr/app/treestat/TaxonSetsPanel.java
index 2912e7a130..85c05b5a1e 100644
--- a/src/dr/app/treestat/TaxonSetsPanel.java
+++ b/src/dr/app/treestat/TaxonSetsPanel.java
@@ -1,5 +1,5 @@
/*
- * TaxonSetsPanel.java
+ * TaxonSetPanel.java
*
* Copyright (c) 2002-2015 Alexei Drummond, Andrew Rambaut and Marc Suchard
*
@@ -25,185 +25,734 @@
package dr.app.treestat;
+import dr.app.beauti.ComboBoxRenderer;
+import dr.app.beauti.util.PanelUtils;
+import dr.app.gui.table.DateCellEditor;
+import dr.evolution.util.Taxa;
+import dr.evolution.util.Taxon;
+import dr.evolution.util.TaxonList;
import jam.framework.Exportable;
+import jam.panels.ActionPanel;
import jam.table.TableRenderer;
+import jam.util.IconUtils;
+import java.awt.*;
+import java.awt.event.*;
+import java.util.ArrayList;
+import java.util.Collections;
import javax.swing.*;
+import javax.swing.border.TitledBorder;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
+import javax.swing.plaf.BorderUIResource;
import javax.swing.table.AbstractTableModel;
-import java.awt.*;
-import java.awt.event.ActionEvent;
-import java.util.ArrayList;
-
-
+import javax.swing.table.JTableHeader;
+import javax.swing.table.TableColumn;
+import javax.swing.table.TableColumnModel;
+import java.util.List;
+
+/**
+ * @author Andrew Rambaut
+ * @author Alexei Drummond
+ * @version $Id: TaxaPanel.java,v 1.1 2006/09/05 13:29:34 rambaut Exp $
+ */
public class TaxonSetsPanel extends JPanel implements Exportable {
+ private static final long serialVersionUID = -3138832889782090814L;
+
+ protected String TAXA;
+ protected String TAXON;
- /**
- *
- */
- private static final long serialVersionUID = -9013475414423166476L;
TreeStatFrame frame = null;
TreeStatData treeStatData = null;
TreeStatData.TaxonSet selectedTaxonSet = null;
- JScrollPane scrollPane1 = null;
- JTable taxonSetsTable = null;
- TaxonSetsTableModel taxonSetsTableModel = null;
+ // private TaxonList taxa = null;
+ protected JTable taxonSetsTable = null;
+ private TableColumnModel tableColumnModel;
+ protected TaxonSetsTableModel taxonSetsTableModel = new TaxonSetsTableModel();
+ ComboBoxRenderer comboBoxRenderer = new ComboBoxRenderer();
- JScrollPane scrollPane2 = null;
- JTable excludedTaxaTable = null;
- TaxaTableModel excludedTaxaTableModel = null;
+ protected JPanel taxonSetEditingPanel = null;
- JScrollPane scrollPane3 = null;
- JTable includedTaxaTable = null;
- TaxaTableModel includedTaxaTableModel = null;
+ protected TreeStatData.TaxonSet currentTaxonSet = null;
- public TaxonSetsPanel(TreeStatFrame frame, TreeStatData treeStatData) {
+ protected final List includedTaxa = new ArrayList<>();
+ protected final List excludedTaxa = new ArrayList<>();
- this.frame = frame;
- setOpaque(false);
+ private JTextField excludedTaxaSearchField = new JTextField();
+
+ protected JTable excludedTaxaTable = null;
+ protected TaxaTableModel excludedTaxaTableModel = null;
+ private JLabel excludedTaxaLabel = new JLabel();
+ protected JComboBox excludedTaxonSetsComboBox = null;
+ protected boolean excludedSelectionChanging = false;
+
+ private JTextField includedTaxaSearchField = new JTextField();
+
+ protected JTable includedTaxaTable = null;
+ protected TaxaTableModel includedTaxaTableModel = null;
+ private JLabel includedTaxaLabel = new JLabel();
+ protected JComboBox includedTaxonSetsComboBox = null;
+ protected boolean includedSelectionChanging = false;
+
+ public TaxonSetsPanel(TreeStatFrame parent, TreeStatData treeStatData) {
+
+ this.frame = parent;
this.treeStatData = treeStatData;
+ setText(false);
- Icon addIcon = null, removeIcon = null, includeIcon = null, excludeIcon = null;
- try {
- addIcon = new ImageIcon(dr.app.util.Utils.getImage(this, "images/add.png"));
- removeIcon = new ImageIcon(dr.app.util.Utils.getImage(this, "images/minus.png"));
- includeIcon = new ImageIcon(dr.app.util.Utils.getImage(this, "images/include.png"));
- excludeIcon = new ImageIcon(dr.app.util.Utils.getImage(this, "images/exclude.png"));
- } catch (Exception e) {
- // do nothing
- }
+ // Taxon Sets
+ initTaxonSetsTable(taxonSetsTableModel);
+
+ initTableColumn();
- JPanel buttonPanel = new JPanel(new BorderLayout());
- buttonPanel.setOpaque(false);
- JButton importButton = new JButton(frame.getImportAction());
- importButton.setFocusable(false);
- importButton.putClientProperty("JButton.buttonType", "textured");
- importButton.setMargin(new Insets(4,4,4,4));
- buttonPanel.add(importButton, BorderLayout.WEST);
- buttonPanel.add(new JLabel(" To define taxon sets, first import a list of taxa (i.e., from the trees to be analysed)"), BorderLayout.SOUTH);
+ initPanel(addTaxonSetAction, removeTaxonSetAction);
+ }
- // Taxon Sets
- taxonSetsTableModel = new TaxonSetsTableModel();
- TableSorter sorter = new TableSorter(taxonSetsTableModel);
- taxonSetsTable = new JTable(sorter);
- sorter.addTableModelListener(taxonSetsTable);
+ protected void setText(boolean useStarBEAST) {
+ if (useStarBEAST) {
+ TAXA = "Species";
+ TAXON = "Species set";
+ } else {
+ TAXA = "Taxa";
+ TAXON = "Taxon set";
+ }
+ }
- taxonSetsTable.getColumnModel().getColumn(0).setCellRenderer(
- new TableRenderer(SwingConstants.LEFT, new Insets(0, 4, 0, 4)));
+ protected void initPanel(Action addTaxonSetAction, Action removeTaxonSetAction) {
+ JScrollPane scrollPane1 = new JScrollPane(taxonSetsTable,
+ JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
+ JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
- taxonSetsTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
- public void valueChanged(ListSelectionEvent evt) { taxonSetsTableSelectionChanged(); }
- });
+ ActionPanel actionPanel1 = new ActionPanel(false);
+ actionPanel1.setAddAction(addTaxonSetAction);
+ actionPanel1.setRemoveAction(removeTaxonSetAction);
- scrollPane1 = new JScrollPane(taxonSetsTable,
- JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
- JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
+ addTaxonSetAction.setEnabled(false);
+ removeTaxonSetAction.setEnabled(false);
- JPanel buttonPanel1 = createAddRemoveButtonPanel(addTaxonSetAction, addIcon, "Create a new taxon set",
- removeTaxonSetAction, removeIcon, "Remove a taxon set",
- javax.swing.BoxLayout.X_AXIS);
+ JPanel controlPanel1 = new JPanel(new FlowLayout(FlowLayout.LEFT));
+ controlPanel1.add(actionPanel1);
// Excluded Taxon List
excludedTaxaTableModel = new TaxaTableModel(false);
- sorter = new TableSorter(excludedTaxaTableModel);
- excludedTaxaTable = new JTable(sorter);
- sorter.addTableModelListener(excludedTaxaTable);
+ excludedTaxaTable = new JTable(excludedTaxaTableModel);
excludedTaxaTable.getColumnModel().getColumn(0).setCellRenderer(
- new TableRenderer(SwingConstants.LEFT, new Insets(0, 4, 0, 4)));
+ new TableRenderer(SwingConstants.LEFT, new Insets(0, 4, 0, 4)));
+ excludedTaxaTable.getColumnModel().getColumn(0).setMinWidth(20);
excludedTaxaTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
- public void valueChanged(ListSelectionEvent evt) { excludedTaxaTableSelectionChanged(); }
+ public void valueChanged(ListSelectionEvent evt) {
+ excludedTaxaTableSelectionChanged();
+ }
});
- scrollPane2 = new JScrollPane(excludedTaxaTable,
- JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
- JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
+ JScrollPane scrollPane2 = new JScrollPane(excludedTaxaTable,
+ JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
+ JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
+
+ includedTaxonSetsComboBox = new JComboBox(new String[]{TAXON.toLowerCase() + "..."});
+ excludedTaxonSetsComboBox = new JComboBox(new String[]{TAXON.toLowerCase() + "..."});
- JPanel buttonPanel2 = createAddRemoveButtonPanel(includeTaxonAction, includeIcon, "Include selected taxa in the taxon set",
- excludeTaxonAction, excludeIcon, "Exclude selected taxa from the taxon set",
- javax.swing.BoxLayout.Y_AXIS);
+ includedTaxaLabel.setText("");
+ excludedTaxaLabel.setText("");
- // Included Taxon List
+ Box panel1 = new Box(BoxLayout.X_AXIS);
+ panel1.add(new JLabel("Select: "));
+ panel1.setOpaque(false);
+ excludedTaxonSetsComboBox.setOpaque(false);
+ panel1.add(excludedTaxonSetsComboBox);
+
+ // Included Taxon List
includedTaxaTableModel = new TaxaTableModel(true);
- sorter = new TableSorter(includedTaxaTableModel);
- includedTaxaTable = new JTable(sorter);
- sorter.addTableModelListener(includedTaxaTable);
+ includedTaxaTable = new JTable(includedTaxaTableModel);
includedTaxaTable.getColumnModel().getColumn(0).setCellRenderer(
- new TableRenderer(SwingConstants.LEFT, new Insets(0, 4, 0, 4)));
+ new TableRenderer(SwingConstants.LEFT, new Insets(0, 4, 0, 4)));
+ includedTaxaTable.getColumnModel().getColumn(0).setMinWidth(20);
includedTaxaTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
- public void valueChanged(ListSelectionEvent evt) { includedTaxaTableSelectionChanged(); }
+ public void valueChanged(ListSelectionEvent evt) {
+ includedTaxaTableSelectionChanged();
+ }
});
+ includedTaxaTable.doLayout();
+
+ JScrollPane scrollPane3 = new JScrollPane(includedTaxaTable,
+ JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
+ JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
+
+ Box panel2 = new Box(BoxLayout.X_AXIS);
+ panel2.add(new JLabel("Select: "));
+ panel2.setOpaque(false);
+ includedTaxonSetsComboBox.setOpaque(false);
+ panel2.add(includedTaxonSetsComboBox);
+
+ Icon includeIcon = null, excludeIcon = null;
+ try {
+ includeIcon = new ImageIcon(IconUtils.getImage(TreeStatApp.class, "images/include.png"));
+ excludeIcon = new ImageIcon(IconUtils.getImage(TreeStatApp.class, "images/exclude.png"));
+ } catch (Exception e) {
+ // do nothing
+ }
- scrollPane3 = new JScrollPane(includedTaxaTable,
- JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
- JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
+ JPanel buttonPanel = createAddRemoveButtonPanel(includeTaxonAction, includeIcon, "Include selected "
+ + TAXA.toLowerCase() + " in the " + TAXON.toLowerCase(),
+ excludeTaxonAction, excludeIcon, "Exclude selected " + TAXA.toLowerCase()
+ + " from the " + TAXON.toLowerCase(), BoxLayout.Y_AXIS);
+
+ taxonSetEditingPanel = new JPanel();
+ taxonSetEditingPanel.setBorder(BorderFactory.createTitledBorder(""));
+ taxonSetEditingPanel.setOpaque(false);
+ taxonSetEditingPanel.setLayout(new GridBagLayout());
+
+ excludedTaxaSearchField.setColumns(12);
+// excludedTaxaSearchField.putClientProperty("JTextField.variant", "search");
+ excludedTaxaSearchField.putClientProperty("Quaqua.TextField.style","search");
+ excludedTaxaSearchField.putClientProperty("Quaqua.TextField.sizeVariant","small");
+ includedTaxaSearchField.setColumns(12);
+// includedTaxaSearchField.putClientProperty("JTextField.variant", "search");
+ includedTaxaSearchField.putClientProperty("Quaqua.TextField.style","search");
+ includedTaxaSearchField.putClientProperty("Quaqua.TextField.sizeVariant","small");
- JPanel panel = new JPanel();
- panel.setOpaque(false);
- panel.setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
- c.weightx = 0.333333;
- c.weighty = 1;
- c.fill = GridBagConstraints.BOTH;
- c.anchor = GridBagConstraints.CENTER;
- c.insets = new Insets(6,6,6,6);
c.gridx = 0;
c.gridy = 0;
- panel.add(scrollPane1, c);
-
- c.weightx = 0.333333;
+ c.weightx = 0.5;
c.weighty = 0;
- c.fill = GridBagConstraints.NONE;
- c.anchor = GridBagConstraints.LINE_START;
- c.insets = new Insets(0,6,6,6);
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.anchor = GridBagConstraints.CENTER;
+ c.insets = new Insets(3, 6, 3, 0);
+ taxonSetEditingPanel.add(excludedTaxaSearchField, c);
+
c.gridx = 0;
c.gridy = 1;
- panel.add(buttonPanel1, c);
-
- c.weightx = 0.333333;
+ c.weightx = 0.5;
c.weighty = 1;
c.fill = GridBagConstraints.BOTH;
c.anchor = GridBagConstraints.CENTER;
- c.insets = new Insets(6,6,6,6);
+ c.insets = new Insets(0, 6, 0, 0);
+ taxonSetEditingPanel.add(scrollPane2, c);
+
+ c.gridx = 0;
+ c.gridy = 2;
+ c.weightx = 0.5;
+ c.weighty = 0;
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.anchor = GridBagConstraints.CENTER;
+ c.insets = new Insets(0, 6, 3, 0);
+ taxonSetEditingPanel.add(excludedTaxaLabel, c);
+
+ c.gridx = 0;
+ c.gridy = 3;
+ c.weightx = 0.5;
+ c.weighty = 0;
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.anchor = GridBagConstraints.CENTER;
+ c.insets = new Insets(0, 6, 3, 0);
+ taxonSetEditingPanel.add(panel1, c);
+
c.gridx = 1;
c.gridy = 0;
- panel.add(scrollPane2, c);
-
- c.weightx = 0.0;
+ c.weightx = 0;
+ c.weighty = 1;
+ c.gridheight = 4;
c.fill = GridBagConstraints.NONE;
c.anchor = GridBagConstraints.CENTER;
- c.insets = new Insets(0,0,0,0);
+ c.insets = new Insets(12, 2, 12, 4);
+ taxonSetEditingPanel.add(buttonPanel, c);
+
c.gridx = 2;
c.gridy = 0;
- panel.add(buttonPanel2, c);
+ c.weightx = 0.5;
+ c.weighty = 0;
+ c.gridheight = 1;
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.anchor = GridBagConstraints.CENTER;
+ c.insets = new Insets(3, 0, 3, 6);
+ taxonSetEditingPanel.add(includedTaxaSearchField, c);
- c.weightx = 0.333333;
+ c.gridx = 2;
+ c.gridy = 1;
+ c.weightx = 0.5;
+ c.weighty = 1;
c.fill = GridBagConstraints.BOTH;
c.anchor = GridBagConstraints.CENTER;
- c.insets = new Insets(6,6,6,6);
- c.gridx = 3;
+ c.insets = new Insets(0, 0, 0, 6);
+ taxonSetEditingPanel.add(scrollPane3, c);
+
+ c.gridx = 2;
+ c.gridy = 2;
+ c.weightx = 0.5;
+ c.weighty = 0;
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.anchor = GridBagConstraints.CENTER;
+ c.insets = new Insets(0, 0, 3, 6);
+ taxonSetEditingPanel.add(includedTaxaLabel, c);
+
+ c.gridx = 2;
+ c.gridy = 3;
+ c.weightx = 0.5;
+ c.weighty = 0;
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.anchor = GridBagConstraints.CENTER;
+ c.insets = new Insets(0, 0, 3, 6);
+ taxonSetEditingPanel.add(panel2, c);
+
+ JPanel panel3 = new JPanel();
+ panel3.setOpaque(false);
+ panel3.setLayout(new GridBagLayout());
+ c = new GridBagConstraints();
+
+ c.gridx = 0;
+ c.gridy = 0;
+ c.weightx = 0.5;
+ c.weighty = 1;
+ c.fill = GridBagConstraints.BOTH;
+ c.anchor = GridBagConstraints.CENTER;
+ c.insets = new Insets(0, 0, 2, 12);
+ panel3.add(scrollPane1, c);
+
+ c.gridx = 0;
+ c.gridy = 1;
+ c.weightx = 0;
+ c.weighty = 0;
+ c.fill = GridBagConstraints.NONE;
+ c.anchor = GridBagConstraints.WEST;
+ c.insets = new Insets(2, 0, 0, 12);
+ panel3.add(actionPanel1, c);
+
+ c.gridx = 1;
c.gridy = 0;
- panel.add(scrollPane3, c);
+ c.weightx = 0.5;
+ c.weighty = 1;
+ c.fill = GridBagConstraints.BOTH;
+ c.anchor = GridBagConstraints.CENTER;
+ c.insets = new Insets(0, 0, 0, 0);
+ panel3.add(taxonSetEditingPanel, c);
+
+ setOpaque(false);
+ setBorder(new BorderUIResource.EmptyBorderUIResource(new Insets(12, 12, 12, 12)));
+ setLayout(new BorderLayout(0, 0));
+ add(panel3, BorderLayout.CENTER);
+
+// taxonSetsTable.addMouseListener(new MouseAdapter() {
+// public void mouseClicked(MouseEvent e) {
+// if (e.getClickCount() == 2) {
+// JTable target = (JTable)e.getSource();
+// int row = target.getSelectedRow();
+// taxonSetsTableDoubleClicked(row);
+// }
+// }
+// });
+
+ includedTaxaSearchField.getDocument().addDocumentListener(new DocumentListener() {
+ public void changedUpdate(DocumentEvent e) {
+ selectIncludedTaxa(includedTaxaSearchField.getText());
+ }
+
+ public void removeUpdate(DocumentEvent e) {
+ selectIncludedTaxa(includedTaxaSearchField.getText());
+ }
+
+ public void insertUpdate(DocumentEvent e) {
+ selectIncludedTaxa(includedTaxaSearchField.getText());
+ }
+ }
+ );
+ excludedTaxaSearchField.getDocument().addDocumentListener(new DocumentListener() {
+ public void changedUpdate(DocumentEvent e) {
+ selectExcludedTaxa(excludedTaxaSearchField.getText());
+ }
+
+ public void removeUpdate(DocumentEvent e) {
+ selectExcludedTaxa(excludedTaxaSearchField.getText());
+ }
+
+ public void insertUpdate(DocumentEvent e) {
+ selectExcludedTaxa(excludedTaxaSearchField.getText());
+ }
+ }
+ );
+
+
+ includedTaxaTable.addMouseListener(new MouseAdapter() {
+ public void mouseClicked(MouseEvent e) {
+ if (e.getClickCount() == 2) {
+ includeSelectedTaxa();
+ }
+ }
+ });
+ excludedTaxaTable.addMouseListener(new MouseAdapter() {
+ public void mouseClicked(MouseEvent e) {
+ if (e.getClickCount() == 2) {
+ excludeSelectedTaxa();
+ }
+ }
+ });
+
+ includedTaxaTable.addFocusListener(new FocusAdapter() {
+ public void focusGained(FocusEvent focusEvent) {
+ excludedTaxaTable.clearSelection();
+ }
+ });
+ excludedTaxaTable.addFocusListener(new FocusAdapter() {
+ public void focusGained(FocusEvent focusEvent) {
+ includedTaxaTable.clearSelection();
+ }
+ });
+
+ includedTaxaTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
+ public void valueChanged(ListSelectionEvent e) {
+ if (!includedSelectionChanging) {
+ if (includedTaxonSetsComboBox.getSelectedIndex() != 0) {
+ includedTaxonSetsComboBox.setSelectedIndex(0);
+ }
+ includedTaxaSearchField.setText("");
+ }
+ }
+ });
+ includedTaxonSetsComboBox.addItemListener(new ItemListener() {
+ public void itemStateChanged(ItemEvent e) {
+ includedSelectionChanging = true;
+ includedTaxaTable.clearSelection();
+ if (includedTaxonSetsComboBox.getSelectedIndex() > 0) {
+ String taxaName = includedTaxonSetsComboBox.getSelectedItem().toString();
+ if (!taxaName.endsWith("...")) {
+ TreeStatData.TaxonSet taxonSet = treeStatData.taxonSets.get(taxaName);
+ if (taxonSet != null) {
+ for (int i = 0; i < taxonSet.taxa.getTaxonCount(); i++) {
+ Taxon taxon = taxonSet.taxa.getTaxon(i);
+ int index = includedTaxa.indexOf(taxon);
+ includedTaxaTable.getSelectionModel().addSelectionInterval(index, index);
+
+ }
+ }
+ }
+ }
+ includedSelectionChanging = false;
+ }
+ });
+
+ excludedTaxaTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
+ public void valueChanged(ListSelectionEvent e) {
+ if (!excludedSelectionChanging) {
+ if (excludedTaxonSetsComboBox.getSelectedIndex() != 0) {
+ excludedTaxonSetsComboBox.setSelectedIndex(0);
+ }
+ excludedTaxaSearchField.setText("");
+ }
+
+ }
+ });
+ excludedTaxonSetsComboBox.addItemListener(new ItemListener() {
+ public void itemStateChanged(ItemEvent e) {
+ excludedSelectionChanging = true;
+ excludedTaxaTable.clearSelection();
+ if (excludedTaxonSetsComboBox.getSelectedIndex() > 0) {
+ String taxaName = excludedTaxonSetsComboBox.getSelectedItem().toString();
+ if (!taxaName.endsWith("...")) {
+ TreeStatData.TaxonSet taxonSet = treeStatData.taxonSets.get(taxaName);
+ if (taxonSet != null) {
+ for (int i = 0; i < taxonSet.taxa.getTaxonCount(); i++) {
+ Taxon taxon = taxonSet.taxa.getTaxon(i);
+ int index = excludedTaxa.indexOf(taxon);
+ excludedTaxaTable.getSelectionModel().addSelectionInterval(index, index);
+
+ }
+ }
+ }
+ }
+ excludedSelectionChanging = false;
+ }
+ });
+
+ includedTaxaTable.doLayout();
+ excludedTaxaTable.doLayout();
+ }
+
+ private void selectIncludedTaxa(String text) {
+ includedSelectionChanging = true;
+ includedTaxaTable.clearSelection();
+ int index = 0;
+ for (Taxon taxon : includedTaxa) {
+ if (taxon.getId().contains(text)) {
+ includedTaxaTable.getSelectionModel().addSelectionInterval(index, index);
+ }
+ index ++;
+
+ }
+ includedSelectionChanging = false;
+ }
+
+ private void selectExcludedTaxa(String text) {
+ excludedSelectionChanging = true;
+ excludedTaxaTable.clearSelection();
+ int index = 0;
+ for (Taxon taxon : excludedTaxa) {
+ if (taxon.getId().contains(text)) {
+ excludedTaxaTable.getSelectionModel().addSelectionInterval(index, index);
+ }
+ index ++;
+
+ }
+ excludedSelectionChanging = false;
+
+ }
+
+ protected void initTableColumn() {
+ tableColumnModel = taxonSetsTable.getColumnModel();
+ TableColumn tableColumn = tableColumnModel.getColumn(0);
+ tableColumn.setCellRenderer(new TableRenderer(SwingConstants.LEFT, new Insets(0, 4, 0, 4)));
+ tableColumn.setMinWidth(20);
+ }
+
+ protected void initTaxonSetsTable(AbstractTableModel tableModel) {
+ taxonSetsTable = new JTable(tableModel);
+ taxonSetsTable.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+
+ taxonSetsTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
+ public void valueChanged(ListSelectionEvent evt) {
+ taxonSetsTableSelectionChanged();
+ }
+ });
+ taxonSetsTable.doLayout();
+ }
+
+ protected void taxonSetChanged() {
+ currentTaxonSet.taxa.removeAllTaxa();
+ for (Taxon anIncludedTaxa : includedTaxa) {
+ currentTaxonSet.taxa.addTaxon(anIncludedTaxa);
+ }
+
+ setupTaxonSetsComboBoxes();
+
+ includedTaxaLabel.setText("" + includedTaxa.size() + " taxa included");
+ excludedTaxaLabel.setText("" + excludedTaxa.size() + " taxa excluded");
+
+ frame.setDirty();
+ }
+
+ protected void resetPanel() {
+// if (!treeStatData.hasData() || treeStatData.taxonSets == null || treeStatData.taxonSets.size() < 1) {
+// setCurrentTaxonSet(null);
+// }
+ }
+
+ public JComponent getExportableComponent() {
+ return taxonSetsTable;
+ }
+
+ private void taxonSetsTableSelectionChanged() {
+ if (taxonSetsTable.getSelectedRowCount() == 0) {
+ selectedTaxonSet = null;
+ removeTaxonSetAction.setEnabled(false);
+ } else {
+ String name = treeStatData.taxonSetNames.get(taxonSetsTable.getSelectedRow());
+ selectedTaxonSet = treeStatData.taxonSets.get(name);
+ removeTaxonSetAction.setEnabled(true);
+ }
+ setCurrentTaxonSet(selectedTaxonSet);
+ includedTaxaTableModel.fireTableDataChanged();
+ excludedTaxaTableModel.fireTableDataChanged();
+ }
+
+// private void taxonSetsTableDoubleClicked(int row) {
+// currentTaxonSet = (Taxa)taxonSets.get(row);
+//
+// Collections.sort(taxonSets);
+// taxonSetsTableModel.fireTableDataChanged();
+//
+// setCurrentTaxonSet(currentTaxonSet);
+//
+// int sel = taxonSets.indexOf(currentTaxonSet);
+// taxonSetsTable.setRowSelectionInterval(sel, sel);
+// }
+
+ Action addTaxonSetAction = new AbstractAction("+") {
- setLayout(new BorderLayout());
- setBorder(BorderFactory.createEmptyBorder(6,6,6,6));
- add(buttonPanel, BorderLayout.NORTH);
- add(panel, BorderLayout.CENTER);
+ private static final long serialVersionUID = 20273987098143413L;
+ public void actionPerformed(ActionEvent ae) {
+ int taxonSetCount = treeStatData.taxonSets.size();
+ TreeStatData.TaxonSet taxonSet = new TreeStatData.TaxonSet();
+ taxonSet.name = "untitled" + taxonSetCount;
+ taxonSet.taxa = new Taxa();
+ treeStatData.taxonSetNames.add(taxonSet.name);
+ treeStatData.taxonSets.put(taxonSet.name, taxonSet);
+ dataChanged();
+
+ int sel = treeStatData.taxonSets.size() - 1;
+ taxonSetsTable.setRowSelectionInterval(sel, sel);
+
+ currentTaxonSet = taxonSet;
+
+ taxonSetChanged();
+
+ taxonSetsTableModel.fireTableDataChanged();
+ }
+ };
+
+ Action removeTaxonSetAction = new AbstractAction("-") {
+
+ private static final long serialVersionUID = 6077578872870122265L;
+
+ public void actionPerformed(ActionEvent ae) {
+ int row = taxonSetsTable.getSelectedRow();
+ if (row != -1) {
+ String name = treeStatData.taxonSetNames.get(row);
+ TreeStatData.TaxonSet taxonSet = treeStatData.taxonSets.remove(name);
+ }
+ taxonSetChanged();
+
+ taxonSetsTableModel.fireTableDataChanged();
+
+ if (row >= treeStatData.taxonSets.size()) {
+ row = treeStatData.taxonSets.size() - 1;
+ }
+ if (row >= 0) {
+ taxonSetsTable.setRowSelectionInterval(row, row);
+ } else {
+ setCurrentTaxonSet(null);
+ }
+ }
+ };
+
+ protected void setCurrentTaxonSet(TreeStatData.TaxonSet taxonSet) {
+
+ this.currentTaxonSet = taxonSet;
+
+ includedTaxa.clear();
+ excludedTaxa.clear();
+
+ if (currentTaxonSet != null) {
+ for (Taxon taxon : taxonSet.taxa) {
+ includedTaxa.add(taxon);
+ }
+ Collections.sort(includedTaxa);
+
+ for (Taxon taxon : treeStatData.allTaxa) {
+ excludedTaxa.add(taxon);
+ }
+ excludedTaxa.removeAll(includedTaxa);
+ Collections.sort(excludedTaxa);
+ }
+
+ setTaxonSetTitle();
+
+ setupTaxonSetsComboBoxes();
+
+ includedTaxaTableModel.fireTableDataChanged();
+ excludedTaxaTableModel.fireTableDataChanged();
+ }
+
+ protected void setTaxonSetTitle() {
+
+ if (currentTaxonSet == null) {
+ taxonSetEditingPanel.setBorder(BorderFactory.createTitledBorder(""));
+ taxonSetEditingPanel.setEnabled(false);
+ } else {
+ taxonSetEditingPanel.setEnabled(true);
+ taxonSetEditingPanel.setBorder(new TitledBorder(null, TAXON + ": " + currentTaxonSet.name, TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.ABOVE_TOP));
+ }
+ }
+
+
+ protected void setupTaxonSetsComboBoxes() {
+ setupTaxonSetsComboBox(excludedTaxonSetsComboBox, excludedTaxa);
+ excludedTaxonSetsComboBox.setSelectedIndex(0);
+ setupTaxonSetsComboBox(includedTaxonSetsComboBox, includedTaxa);
+ includedTaxonSetsComboBox.setSelectedIndex(0);
+ }
+
+ protected void setupTaxonSetsComboBox(JComboBox comboBox, List availableTaxa) {
+ comboBox.removeAllItems();
+
+ comboBox.addItem(TAXON.toLowerCase() + "...");
+ for (TreeStatData.TaxonSet taxonSet : treeStatData.taxonSets.values()) {
+ // AR - as these comboboxes are just intended to be handy ways of selecting taxa, I have removed
+ // these requirements (it was just confusing why they weren't in the lists.
+// if (taxa != currentTaxonSet) {
+// if (isCompatible(taxa, availableTaxa)) {
+ comboBox.addItem(taxonSet.name); // have to add String, otherwise it will throw Exception to cast "taxa..." into Taxa
+// }
+// }
+ }
+ }
+
+ /**
+ * The table on the left side of panel
+ */
+ protected class TaxonSetsTableModel extends AbstractTableModel {
+ private static final long serialVersionUID = 3318461381525023153L;
+
+ String[] columnNames = {"Taxon Set"};
+
+ public TaxonSetsTableModel() {
+ }
+
+ public int getColumnCount() {
+ return columnNames.length;
+ }
+
+ public String getColumnName(int column) {
+ return columnNames[column];
+ }
+
+ public int getRowCount() {
+ if (treeStatData == null) return 0;
+ return treeStatData.taxonSets.size();
+ }
+
+ public Object getValueAt(int rowIndex, int columnIndex) {
+ String name = treeStatData.taxonSetNames.get(rowIndex);
+ TreeStatData.TaxonSet taxonSet = treeStatData.taxonSets.get(name);
+ switch (columnIndex) {
+ case 0:
+ return taxonSet.name;
+ default:
+ throw new IllegalArgumentException("unknown column, " + columnIndex);
+ }
+ }
+
+ public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
+// Taxa taxonSet = treeStatData.taxonSets.get(rowIndex);
+ TreeStatData.TaxonSet taxonSet = treeStatData.taxonSets.get(rowIndex);
+ switch (columnIndex) {
+ case 0:
+ taxonSet.name=aValue.toString();
+ setTaxonSetTitle();
+ break;
+
+ default:
+ throw new IllegalArgumentException("unknown column, " + columnIndex);
+ }
+ }
+
+ public boolean isCellEditable(int row, int col) {
+ return true;
+ }
+
+ public Class getColumnClass(int columnIndex) {
+ switch (columnIndex) {
+ case 0:
+ return String.class;
+ default:
+ throw new IllegalArgumentException("unknown column, " + columnIndex);
+ }
+ }
}
- JPanel createAddRemoveButtonPanel(Action addAction, Icon addIcon, String addToolTip,
- Action removeAction, Icon removeIcon, String removeToolTip, int axis) {
+ protected JPanel createAddRemoveButtonPanel(Action addAction, Icon addIcon, String addToolTip,
+ Action removeAction, Icon removeIcon, String removeToolTip, int axis) {
- JPanel buttonPanel = new JPanel();
+ JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new BoxLayout(buttonPanel, axis));
buttonPanel.setOpaque(false);
JButton addButton = new JButton(addAction);
@@ -211,8 +760,9 @@ JPanel createAddRemoveButtonPanel(Action addAction, Icon addIcon, String addTool
addButton.setIcon(addIcon);
addButton.setText(null);
}
- addButton.setToolTipText(addToolTip);
- addButton.putClientProperty("JButton.buttonType", "textured");
+ addButton.setToolTipText(addToolTip);
+ addButton.putClientProperty("JButton.buttonType", "roundRect");
+ // addButton.putClientProperty("JButton.buttonType", "toolbar");
addButton.setOpaque(false);
addAction.setEnabled(false);
@@ -221,13 +771,14 @@ JPanel createAddRemoveButtonPanel(Action addAction, Icon addIcon, String addTool
removeButton.setIcon(removeIcon);
removeButton.setText(null);
}
- removeButton.setToolTipText(removeToolTip);
- removeButton.putClientProperty("JButton.buttonType", "textured");
+ removeButton.setToolTipText(removeToolTip);
+ removeButton.putClientProperty("JButton.buttonType", "roundRect");
+// removeButton.putClientProperty("JButton.buttonType", "toolbar");
removeButton.setOpaque(false);
removeAction.setEnabled(false);
buttonPanel.add(addButton);
- buttonPanel.add(new JToolBar.Separator(new Dimension(6,6)));
+ buttonPanel.add(new JToolBar.Separator(new Dimension(6, 6)));
buttonPanel.add(removeButton);
return buttonPanel;
@@ -242,18 +793,6 @@ public void dataChanged() {
excludedTaxaTableModel.fireTableDataChanged();
}
- private void taxonSetsTableSelectionChanged() {
- if (taxonSetsTable.getSelectedRowCount() == 0) {
- selectedTaxonSet = null;
- removeTaxonSetAction.setEnabled(false);
- } else {
- selectedTaxonSet = treeStatData.taxonSets.get(taxonSetsTable.getSelectedRow());
- removeTaxonSetAction.setEnabled(true);
- }
- includedTaxaTableModel.fireTableDataChanged();
- excludedTaxaTableModel.fireTableDataChanged();
- }
-
private void excludedTaxaTableSelectionChanged() {
if (excludedTaxaTable.getSelectedRowCount() == 0) {
includeTaxonAction.setEnabled(false);
@@ -270,128 +809,84 @@ private void includedTaxaTableSelectionChanged() {
}
}
- public JComponent getExportableComponent() {
- return this;
- }
+ private void includeSelectedTaxa() {
+ int[] rows = excludedTaxaTable.getSelectedRows();
- Action addTaxonSetAction = new AbstractAction("+") {
+ List transfer = new ArrayList();
- /**
- *
- */
- private static final long serialVersionUID = 1831933175582860833L;
-
- public void actionPerformed(ActionEvent ae) {
- TreeStatData.TaxonSet taxonSet = new TreeStatData.TaxonSet();
- taxonSet.name = "untitled";
- taxonSet.taxa = new ArrayList();
- treeStatData.taxonSets.add(taxonSet);
- dataChanged();
+ for (int r : rows) {
+ transfer.add(excludedTaxa.get(r));
+ }
- int sel = treeStatData.taxonSets.size() - 1;
- taxonSetsTable.setRowSelectionInterval(sel, sel);
- }
- };
+ includedTaxa.addAll(transfer);
+ Collections.sort(includedTaxa);
- Action removeTaxonSetAction = new AbstractAction("-") {
+ excludedTaxa.removeAll(includedTaxa);
- /**
- *
- */
- private static final long serialVersionUID = -8662527333546044639L;
+ includedTaxaTableModel.fireTableDataChanged();
+ excludedTaxaTableModel.fireTableDataChanged();
- public void actionPerformed(ActionEvent ae) {
- int saved = taxonSetsTable.getSelectedRow();
- int row = taxonSetsTable.getSelectedRow();
- if (row != -1) {
- treeStatData.taxonSets.remove(row);
- }
- dataChanged();
- if (saved >= treeStatData.taxonSets.size()) saved = treeStatData.taxonSets.size() - 1;
- taxonSetsTable.setRowSelectionInterval(saved, saved);
- }
- };
+ includedTaxaTable.getSelectionModel().clearSelection();
+ for (Taxon taxon : transfer) {
+ int row = includedTaxa.indexOf(taxon);
+ includedTaxaTable.getSelectionModel().addSelectionInterval(row, row);
+ }
- Action includeTaxonAction = new AbstractAction("->") {
- /**
- *
- */
- private static final long serialVersionUID = -1875904513948242608L;
+ taxonSetChanged();
+ }
- public void actionPerformed(ActionEvent ae) {
- int saved = taxonSetsTable.getSelectedRow();
- int[] rows = excludedTaxaTable.getSelectedRows();
- ArrayList exclList = new ArrayList(treeStatData.allTaxa);
- exclList.removeAll(selectedTaxonSet.taxa);
- for (int row : rows) {
- selectedTaxonSet.taxa.add(exclList.get(row));
- }
- dataChanged();
- taxonSetsTable.setRowSelectionInterval(saved, saved);
- }
- };
+ private void excludeSelectedTaxa() {
+ int[] rows = includedTaxaTable.getSelectedRows();
- Action excludeTaxonAction = new AbstractAction("<-") {
+ List transfer = new ArrayList();
- /**
- *
- */
- private static final long serialVersionUID = 4523480086490780822L;
+ for (int r : rows) {
+ transfer.add(includedTaxa.get(r));
+ }
- public void actionPerformed(ActionEvent ae) {
- int saved = taxonSetsTable.getSelectedRow();
- int[] rows = includedTaxaTable.getSelectedRows();
- for (int i = rows.length - 1; i >= 0 ; i--) {
- selectedTaxonSet.taxa.remove(rows[i]);
- }
- dataChanged();
- taxonSetsTable.setRowSelectionInterval(saved, saved);
- }
- };
+ excludedTaxa.addAll(transfer);
+ Collections.sort(excludedTaxa);
- class TaxonSetsTableModel extends AbstractTableModel {
+ includedTaxa.removeAll(excludedTaxa);
- /**
- *
- */
- private static final long serialVersionUID = 219223813257870207L;
+ includedTaxaTableModel.fireTableDataChanged();
+ excludedTaxaTableModel.fireTableDataChanged();
- public TaxonSetsTableModel() {
+ excludedTaxaTable.getSelectionModel().clearSelection();
+ for (Taxon taxon : transfer) {
+ int row = excludedTaxa.indexOf(taxon);
+ excludedTaxaTable.getSelectionModel().addSelectionInterval(row, row);
}
- public int getColumnCount() {
- return 1;
- }
+ taxonSetChanged();
+ }
- public int getRowCount() {
- return treeStatData.taxonSets.size();
- }
+ Action includeTaxonAction = new AbstractAction("->") {
+ /**
+ *
+ */
+ private static final long serialVersionUID = 7510299673661594128L;
- public Object getValueAt(int row, int col) {
- return (treeStatData.taxonSets.get(row)).name;
+ public void actionPerformed(ActionEvent ae) {
+ includeSelectedTaxa();
}
+ };
- public void setValueAt(Object value, int row, int col) {
- (treeStatData.taxonSets.get(row)).name = (String)value;
- }
+ Action excludeTaxonAction = new AbstractAction("<-") {
- public boolean isCellEditable(int row, int col) {
- return true;
- }
+ /**
+ *
+ */
+ private static final long serialVersionUID = 449692708602410206L;
- public String getColumnName(int column) {
- return "Taxon Sets";
+ public void actionPerformed(ActionEvent ae) {
+ excludeSelectedTaxa();
}
+ };
- public Class getColumnClass(int c) {return getValueAt(0, c).getClass();}
- }
-
- class TaxaTableModel extends AbstractTableModel {
+ class TaxaTableModel extends AbstractTableModel {
- /**
- *
- */
- private static final long serialVersionUID = 1559408662356843275L;
+ private static final long serialVersionUID = -8027482229525938010L;
boolean included;
public TaxaTableModel(boolean included) {
@@ -403,35 +898,36 @@ public int getColumnCount() {
}
public int getRowCount() {
- if (selectedTaxonSet == null) return 0;
+ if (currentTaxonSet == null) return 0;
if (included) {
- return selectedTaxonSet.taxa.size();
+ return includedTaxa.size();
} else {
- return treeStatData.allTaxa.size() - selectedTaxonSet.taxa.size();
+ return excludedTaxa.size();
}
}
public Object getValueAt(int row, int col) {
if (included) {
- return selectedTaxonSet.taxa.get(row);
+ return includedTaxa.get(row).getId();
} else {
- ArrayList exclList = new ArrayList(treeStatData.allTaxa);
- exclList.removeAll(selectedTaxonSet.taxa);
- return exclList.get(row);
+ return excludedTaxa.get(row).getId();
}
}
- public boolean isCellEditable(int row, int col) {
- return false;
- }
+ public boolean isCellEditable(int row, int col) {
+ return false;
+ }
public String getColumnName(int column) {
- if (included) return "Included Taxa";
- else return "Excluded Taxa";
+ if (included) return "Included " + TAXA;
+ else return "Excluded " + TAXA;
}
- public Class getColumnClass(int c) {return getValueAt(0, c).getClass();}
+ public Class getColumnClass(int c) {
+ return getValueAt(0, c).getClass();
+ }
}
+
}
diff --git a/src/dr/app/treestat/TreeStatData.java b/src/dr/app/treestat/TreeStatData.java
index cdc817df03..87a4d7436f 100644
--- a/src/dr/app/treestat/TreeStatData.java
+++ b/src/dr/app/treestat/TreeStatData.java
@@ -26,13 +26,13 @@
package dr.app.treestat;
import dr.app.treestat.statistics.SummaryStatisticDescription;
+import dr.evolution.util.Taxa;
+import dr.evolution.util.Taxon;
+import dr.evolution.util.TaxonList;
import org.jdom.Document;
import org.jdom.Element;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
+import java.util.*;
public class TreeStatData {
public static final String version = "1.0";
@@ -41,14 +41,15 @@ public TreeStatData() {
}
// Data options
- public Set allTaxa = new HashSet();
- public List taxonSets = new ArrayList();
+ public Set allTaxa = new HashSet<>();
+ public List taxonSetNames = new ArrayList<>();
+ public Map taxonSets = new HashMap<>();
public List characters = new ArrayList();
public List statistics = new ArrayList();
public static class TaxonSet {
String name;
- List taxa;
+ Taxa taxa;
public String toString() { return name; }
}
diff --git a/src/dr/app/treestat/TreeStatFrame.java b/src/dr/app/treestat/TreeStatFrame.java
index 47fb7f296c..1c26277676 100644
--- a/src/dr/app/treestat/TreeStatFrame.java
+++ b/src/dr/app/treestat/TreeStatFrame.java
@@ -26,6 +26,7 @@
package dr.app.treestat;
import dr.evolution.tree.TreeUtils;
+import dr.evolution.util.Taxon;
import jam.framework.Application;
import jam.framework.DocumentFrame;
import jam.util.IconUtils;
@@ -34,6 +35,7 @@
import javax.swing.plaf.BorderUIResource;
import java.awt.*;
import java.io.*;
+import java.util.HashSet;
import dr.evolution.io.Importer;
import dr.evolution.io.NexusImporter;
@@ -190,7 +192,10 @@ protected void importFromFile(File file) throws IOException, Importer.ImportExce
tree = importer.importTree(null);
}
- treeStatData.allTaxa = TreeUtils.getLeafSet(tree);
+ treeStatData.allTaxa = new HashSet();
+ for (String taxonName : TreeUtils.getLeafSet(tree)) {
+ treeStatData.allTaxa.add(new Taxon(taxonName));
+ }
statusLabel.setText(Integer.toString(treeStatData.allTaxa.size()) + " taxa loaded.");
reader.close();
diff --git a/src/dr/evolution/alignment/GapStrippedAlignment.java b/src/dr/evolution/alignment/GapStrippedAlignment.java
index ac3218ca51..9dc75e4790 100644
--- a/src/dr/evolution/alignment/GapStrippedAlignment.java
+++ b/src/dr/evolution/alignment/GapStrippedAlignment.java
@@ -103,6 +103,10 @@ public final Object getSequenceAttribute(int index, String name) {
throw new UnsupportedOperationException();
}
+ public List getSequences() {
+ return alignment.getSequences();
+ }
+
public final int getTaxonCount() {
return alignment.getTaxonCount();
}
diff --git a/src/dr/evolution/alignment/SimpleAlignment.java b/src/dr/evolution/alignment/SimpleAlignment.java
index 4db4f967c3..5176f96c7d 100644
--- a/src/dr/evolution/alignment/SimpleAlignment.java
+++ b/src/dr/evolution/alignment/SimpleAlignment.java
@@ -188,7 +188,7 @@ public void addSequence(Sequence sequence) {
throw new IllegalArgumentException("Sequence's dataType does not match the alignment's");
}
- int invalidCharAt = sequence.getInvalidChar();
+ int invalidCharAt = sequence.getInvalidChar(dataType);
if (invalidCharAt >= 0)
throw new IllegalArgumentException("Sequence of " + sequence.getTaxon().getId()
+ " contains invalid char \'" + sequence.getChar(invalidCharAt) + "\' at index " + invalidCharAt);
@@ -214,7 +214,7 @@ public void insertSequence(int position, Sequence sequence) {
throw new IllegalArgumentException("Sequence's dataType does not match the alignment's");
}
- int invalidCharAt = sequence.getInvalidChar();
+ int invalidCharAt = sequence.getInvalidChar(dataType);
if (invalidCharAt >= 0)
throw new IllegalArgumentException("Sequence of " + sequence.getTaxon().getId()
+ " contains invalid char \'" + sequence.getChar(invalidCharAt) + "\' at index " + invalidCharAt);
diff --git a/src/dr/evolution/alignment/SitePatterns.java b/src/dr/evolution/alignment/SitePatterns.java
index dcf4757bd9..ae92699450 100644
--- a/src/dr/evolution/alignment/SitePatterns.java
+++ b/src/dr/evolution/alignment/SitePatterns.java
@@ -420,7 +420,7 @@ private int addPattern(int[] pattern, int weight, double[][] uncertainty) {
}
/**
- * @return true if the pattern is invariant
+ * @return true if the pattern contains a gap state
*/
private boolean isGapped(int[] pattern) {
int len = pattern.length;
@@ -434,7 +434,7 @@ private boolean isGapped(int[] pattern) {
}
/**
- * @return true if the pattern is invariant
+ * @return true if the pattern contains an ambiguous state
*/
private boolean isAmbiguous(int[] pattern) {
int len = pattern.length;
@@ -448,7 +448,7 @@ private boolean isAmbiguous(int[] pattern) {
}
/**
- * @return true if the pattern is invariant
+ * @return true if the pattern contains an unknown state
*/
private boolean isUnknown(int[] pattern) {
int len = pattern.length;
diff --git a/src/dr/evolution/alignment/WrappedAlignment.java b/src/dr/evolution/alignment/WrappedAlignment.java
index a08237ee74..7ebd65662f 100644
--- a/src/dr/evolution/alignment/WrappedAlignment.java
+++ b/src/dr/evolution/alignment/WrappedAlignment.java
@@ -33,6 +33,7 @@
import dr.evolution.util.Taxon;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.Iterator;
import java.util.List;
@@ -181,6 +182,10 @@ public Object getSequenceAttribute(int index, String name) {
return alignment.getSequenceAttribute(index, name);
}
+ public List getSequences() {
+ return alignment.getSequences();
+ }
+
/**
* @return a count of the number of taxa in the list.
*/
diff --git a/src/dr/evolution/datatype/GeneralDataType.java b/src/dr/evolution/datatype/GeneralDataType.java
index cb502ae6f1..a30441b5f8 100644
--- a/src/dr/evolution/datatype/GeneralDataType.java
+++ b/src/dr/evolution/datatype/GeneralDataType.java
@@ -127,9 +127,19 @@ public void addAmbiguity(String code, String[] ambiguousStates) {
@Override
public char[] getValidChars() {
- return null;
+ if (validChars == null) {
+ validChars = new char[stateMap.size()];
+ int i = 0;
+ for (String state : stateMap.keySet()) {
+ validChars[i] = state.charAt(0);
+ i++;
+ }
+ }
+ return validChars;
}
+ private char[] validChars = null;
+
/**
* Get state corresponding to a code
*
@@ -197,28 +207,34 @@ public int[] getStates(int state) {
*/
public boolean[] getStateSet(int state) {
- boolean[] stateSet = new boolean[stateCount];
-
- if (state < states.size()) {
- State s = states.get(state);
-
- for (int i = 0; i < stateCount; i++) {
- stateSet[i] = false;
+ boolean[] stateSet = stateSetMap.get(state);
+
+ if (stateSet == null) {
+ stateSet = new boolean[stateCount];
+ if (state >= 0 && state < states.size()) {
+ State s = states.get(state);
+
+ for (int i = 0; i < stateCount; i++) {
+ stateSet[i] = false;
+ }
+ for (int i = 0, n = s.ambiguities.length; i < n; i++) {
+ stateSet[s.ambiguities[i]] = true;
+ }
+ } else if (state == states.size()) {
+ for (int i = 0; i < stateCount; i++) {
+ stateSet[i] = true;
+ }
+ } else {
+ throw new IllegalArgumentException("invalid state index");
}
- for (int i = 0, n = s.ambiguities.length; i < n; i++) {
- stateSet[s.ambiguities[i]] = true;
- }
- } else if (state == states.size()) {
- for (int i = 0; i < stateCount; i++) {
- stateSet[i] = true;
- }
- } else {
- throw new IllegalArgumentException("invalid state index");
+ stateSetMap.put(state, stateSet);
}
return stateSet;
}
+ private Map stateSetMap = new HashMap<>();
+
/**
* description of data type
*
diff --git a/src/dr/evolution/sequence/Sequence.java b/src/dr/evolution/sequence/Sequence.java
index 9b8f630849..31371c4208 100644
--- a/src/dr/evolution/sequence/Sequence.java
+++ b/src/dr/evolution/sequence/Sequence.java
@@ -132,7 +132,7 @@ public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin) {
/**
* search invalid character in the sequence by given data type, and return its index
*/
- public int getInvalidChar() {
+ public int getInvalidChar(DataType dataType) {
final char[] validChars = dataType.getValidChars();
if (validChars != null) {
String validString = new String(validChars);
diff --git a/src/dr/evolution/sequence/SequenceList.java b/src/dr/evolution/sequence/SequenceList.java
index ae96c39fc0..d842bba878 100644
--- a/src/dr/evolution/sequence/SequenceList.java
+++ b/src/dr/evolution/sequence/SequenceList.java
@@ -27,6 +27,8 @@
import dr.evolution.util.TaxonList;
+import java.util.List;
+
/**
* Interface for a list of sequences.
*
@@ -61,5 +63,9 @@ public interface SequenceList extends TaxonList {
*/
public Object getSequenceAttribute(int index, String name);
+ /**
+ * @return an immutable iterable List of sequences
+ */
+ public List getSequences();
}
diff --git a/src/dr/evolution/sequence/Sequences.java b/src/dr/evolution/sequence/Sequences.java
index e792e87006..e4115841d2 100644
--- a/src/dr/evolution/sequence/Sequences.java
+++ b/src/dr/evolution/sequence/Sequences.java
@@ -29,10 +29,7 @@
import dr.util.Attributable;
import dr.util.Identifiable;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Vector;
+import java.util.*;
/**
* Class for storing sequences.
@@ -88,6 +85,10 @@ public Object getSequenceAttribute(int index, String name) {
return sequence.getAttribute(name);
}
+ public List getSequences() {
+ return Collections.unmodifiableList(sequences);
+ }
+
// **************************************************************
// TaxonList IMPLEMENTATION
// **************************************************************
diff --git a/src/dr/evolution/sequence/UncertainSequence.java b/src/dr/evolution/sequence/UncertainSequence.java
index 57de33b1a3..3adb6051dd 100644
--- a/src/dr/evolution/sequence/UncertainSequence.java
+++ b/src/dr/evolution/sequence/UncertainSequence.java
@@ -1,5 +1,7 @@
package dr.evolution.sequence;
+import dr.evolution.datatype.DataType;
+
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
@@ -50,7 +52,7 @@ public void setState(int index, int state) {
}
@Override
- public int getInvalidChar() {
+ public int getInvalidChar(DataType dataType) {
checkParsed();
diff --git a/src/dr/evomodel/branchratemodel/LocalClockModel.java b/src/dr/evomodel/branchratemodel/LocalClockModel.java
index 52a450765e..1fcccba71c 100644
--- a/src/dr/evomodel/branchratemodel/LocalClockModel.java
+++ b/src/dr/evomodel/branchratemodel/LocalClockModel.java
@@ -113,20 +113,26 @@ public void addExternalBranchClock(TaxonList taxonList, BranchRateModel branchRa
addModel(branchRates);
}
- public void addCladeClock(TaxonList taxonList, Parameter rateParameter, boolean isRelativeRate, double stemProportion, boolean excludeClade) throws TreeUtils.MissingTaxonException {
+ public void addCladeClock(TaxonList taxonList, Parameter rateParameter, boolean isRelativeRate, Parameter stemParameter, boolean stemAsTime, boolean excludeClade) throws TreeUtils.MissingTaxonException {
Set tips = TreeUtils.getTipsForTaxa(treeModel, taxonList);
BitSet tipBitSet = TreeUtils.getTipsBitSetForTaxa(treeModel, taxonList);
- LocalClock clock = new LocalClock(rateParameter, isRelativeRate, tips, stemProportion, excludeClade);
+ LocalClock clock = new LocalClock(rateParameter, isRelativeRate, tips, stemParameter, stemAsTime, excludeClade);
localCladeClocks.put(tipBitSet, clock);
addVariable(rateParameter);
+ if (stemParameter != null) {
+ addVariable(stemParameter);
+ }
}
- public void addCladeClock(TaxonList taxonList, BranchRateModel branchRates, boolean isRelativeRate, double stemProportion, boolean excludeClade) throws TreeUtils.MissingTaxonException {
+ public void addCladeClock(TaxonList taxonList, BranchRateModel branchRates, boolean isRelativeRate, Parameter stemParameter, boolean stemAsTime, boolean excludeClade) throws TreeUtils.MissingTaxonException {
Set tips = TreeUtils.getTipsForTaxa(treeModel, taxonList);
BitSet tipBitSet = TreeUtils.getTipsBitSetForTaxa(treeModel, taxonList);
- LocalClock clock = new LocalClock(branchRates, isRelativeRate, tips, stemProportion, excludeClade);
+ LocalClock clock = new LocalClock(branchRates, isRelativeRate, tips, stemParameter, stemAsTime, excludeClade);
localCladeClocks.put(tipBitSet, clock);
addModel(branchRates);
+ if (stemParameter != null) {
+ addVariable(stemParameter);
+ }
}
public void addTrunkClock(TaxonList taxonList, Parameter rateParameter, Parameter indexParameter, boolean isRelativeRate) throws TreeUtils.MissingTaxonException {
@@ -249,6 +255,7 @@ public double getBranchRate(final Tree tree, final NodeRef node) {
if (localClock != null) {
double parentRate = rate;
double stemProportion = 1.0;
+ double stemTime = 0.0;
if (localClock != parentClock) {
// this is the branch where the rate switch occurs
@@ -259,7 +266,19 @@ public double getBranchRate(final Tree tree, final NodeRef node) {
parentRate = localClock.getBranchRate(tree, tree.getParent(node));
}
}
- stemProportion = localClock.getStemProportion();
+ if (localClock.stemAsTime) {
+ // this could be greater than 1 in which case bad things might happen
+ stemTime = localClock.getStemValue();
+ stemProportion = stemTime / tree.getBranchLength(node);
+
+ if (stemProportion > 1.0) {
+ // it should be ensured that this never happens.
+ throw new IllegalArgumentException("A stem proportion for a local clock is > 1.0");
+ }
+ } else {
+ stemProportion = localClock.getStemValue();
+ stemTime = tree.getBranchLength(node) * stemProportion;
+ }
}
if (localClock.isRelativeRate()) {
@@ -424,7 +443,8 @@ private class LocalClock {
this.tips = tipSet;
this.tipList = null;
this.type = type;
- this.stemProportion = 1.0;
+ this.stemParameter = null;
+ this.stemAsTime = false;
this.excludeClade = true;
}
@@ -436,11 +456,12 @@ private class LocalClock {
this.tips = tipSet;
this.tipList = null;
this.type = type;
- this.stemProportion = 1.0;
+ this.stemParameter = null;
+ this.stemAsTime = false;
this.excludeClade = true;
}
- LocalClock(Parameter rateParameter, boolean isRelativeRate, Set tips, double stemProportion, boolean excludeClade) {
+ LocalClock(Parameter rateParameter, boolean isRelativeRate, Set tips, Parameter stemParameter, boolean stemAsTime, boolean excludeClade) {
this.rateParameter = rateParameter;
this.branchRates = null;
this.indexParameter = null;
@@ -448,11 +469,12 @@ private class LocalClock {
this.tips = tips;
this.tipList = null;
this.type = ClockType.CLADE;
- this.stemProportion = stemProportion;
+ this.stemParameter = stemParameter;
+ this.stemAsTime = stemAsTime;
this.excludeClade = excludeClade;
}
- LocalClock(BranchRateModel branchRates, boolean isRelativeRate, Set tips, double stemProportion, boolean excludeClade) {
+ LocalClock(BranchRateModel branchRates, boolean isRelativeRate, Set tips, Parameter stemParameter, boolean stemAsTime, boolean excludeClade) {
this.rateParameter = null;
this.branchRates = branchRates;
this.indexParameter = null;
@@ -460,7 +482,8 @@ private class LocalClock {
this.tips = tips;
this.tipList = null;
this.type = ClockType.CLADE;
- this.stemProportion = stemProportion;
+ this.stemParameter = stemParameter;
+ this.stemAsTime = stemAsTime;
this.excludeClade = excludeClade;
}
@@ -472,7 +495,8 @@ private class LocalClock {
this.tips = null;
this.tipList = tipList;
this.type = type;
- this.stemProportion = 1.0;
+ this.stemParameter = null;
+ this.stemAsTime = false;
this.excludeClade = true;
}
@@ -484,12 +508,18 @@ private class LocalClock {
this.tips = null;
this.tipList = tipList;
this.type = type;
- this.stemProportion = 1.0;
+ this.stemParameter = null;
+ this.stemAsTime = false;
this.excludeClade = true;
}
- double getStemProportion() {
- return this.stemProportion;
+ double getStemValue() {
+ if (stemParameter != null) {
+ return stemParameter.getParameterValue(0);
+ } else {
+ // if no parameter then default to 0 stem
+ return 0.0;
+ }
}
boolean excludeClade() {
@@ -519,7 +549,8 @@ boolean isRelativeRate() {
private final Set tips;
private final List tipList;
private final ClockType type;
- private final double stemProportion;
+ private final Parameter stemParameter;
+ private final boolean stemAsTime;
private final boolean excludeClade;
}
diff --git a/src/dr/evomodel/coalescent/TreeIntervals.java b/src/dr/evomodel/coalescent/TreeIntervals.java
index 233304034f..32d9833d6e 100644
--- a/src/dr/evomodel/coalescent/TreeIntervals.java
+++ b/src/dr/evomodel/coalescent/TreeIntervals.java
@@ -216,6 +216,7 @@ private void collectTimes(Tree tree, NodeRef node, Set excludeNodesBelo
}
if (!include || tree.isExternal(child)) {
+ // the mrca of the clade below that is being excluded becomes a sampling event
intervals.addSampleEvent(tree.getNodeHeight(child));
} else {
collectTimes(tree, child, excludeNodesBelow, intervals);
diff --git a/src/dr/evomodel/siteratemodel/GammaSiteRateModel.java b/src/dr/evomodel/siteratemodel/GammaSiteRateModel.java
index 93239e766c..61e5d954f1 100644
--- a/src/dr/evomodel/siteratemodel/GammaSiteRateModel.java
+++ b/src/dr/evomodel/siteratemodel/GammaSiteRateModel.java
@@ -43,6 +43,10 @@
*/
public class GammaSiteRateModel extends AbstractModel implements SiteRateModel, Citable {
+ public enum CategoryWidthType {
+ FASTEST,
+ GEOMETRIC
+ };
public GammaSiteRateModel(String name) {
this( name,
@@ -50,7 +54,7 @@ public GammaSiteRateModel(String name) {
1.0,
null,
0,
- null);
+ null, null, null);
}
public GammaSiteRateModel(String name, double alpha, int categoryCount) {
@@ -59,25 +63,28 @@ public GammaSiteRateModel(String name, double alpha, int categoryCount) {
1.0,
new Parameter.Default(alpha),
categoryCount,
- null);
+ null, null, null);
}
- public GammaSiteRateModel(String name, double pInvar) {
+ public GammaSiteRateModel(String name, double alpha, int categoryCount, double pInvar) {
this( name,
null,
1.0,
- null,
- 0,
- new Parameter.Default(pInvar));
+ new Parameter.Default(alpha),
+ categoryCount,
+ new Parameter.Default(pInvar),
+ null, null);
}
- public GammaSiteRateModel(String name, double alpha, int categoryCount, double pInvar) {
+ public GammaSiteRateModel(String name, double alpha, int categoryCount, double pInvar, double catWidth, CategoryWidthType categoryWidthType) {
this( name,
null,
1.0,
new Parameter.Default(alpha),
categoryCount,
- new Parameter.Default(pInvar));
+ new Parameter.Default(pInvar),
+ new Parameter.Default(catWidth),
+ categoryWidthType);
}
public GammaSiteRateModel(
@@ -85,7 +92,7 @@ public GammaSiteRateModel(
Parameter nuParameter,
Parameter shapeParameter, int gammaCategoryCount,
Parameter invarParameter) {
- this(name, nuParameter, 1.0, shapeParameter, gammaCategoryCount, invarParameter);
+ this(name, nuParameter, 1.0, shapeParameter, gammaCategoryCount, invarParameter, null, null);
}
/**
@@ -97,7 +104,9 @@ public GammaSiteRateModel(
Parameter nuParameter,
double muWeight,
Parameter shapeParameter, int gammaCategoryCount,
- Parameter invarParameter) {
+ Parameter invarParameter,
+ Parameter categoryWidthParameter,
+ CategoryWidthType categoryWidthType) {
super(name);
@@ -130,6 +139,13 @@ public GammaSiteRateModel(
invarParameter.addBounds(new Parameter.DefaultBounds(1.0, 0.0, 1));
}
+ this.categoryWidthParameter = categoryWidthParameter;
+ this.categoryWidthType = categoryWidthType;
+ if (categoryWidthParameter != null) {
+ addVariable(categoryWidthParameter);
+ categoryWidthParameter.addBounds(new Parameter.DefaultBounds(Double.POSITIVE_INFINITY, 0.0, 1));
+ }
+
categoryRates = new double[this.categoryCount];
categoryProportions = new double[this.categoryCount];
@@ -165,35 +181,8 @@ public final double getAlpha() {
return shapeParameter.getParameterValue(0);
}
-
- public Parameter getAlphaParameter() {
- return shapeParameter;
- }
-
- public Parameter getPInvParameter() {
- return invarParameter;
- }
-
- public Parameter setRelativeRateParameter() {
- return nuParameter;
- }
-
- public void setAlphaParameter(Parameter parameter) {
- if (shapeParameter != null) removeVariable(shapeParameter);
- shapeParameter = parameter;
- if (shapeParameter != null) addVariable(shapeParameter);
- }
-
- public void setPInvParameter(Parameter parameter) {
- if (invarParameter != null) removeVariable(invarParameter);
- invarParameter = parameter;
- if (invarParameter != null) addVariable(invarParameter);
- }
-
- public void setRelativeRateParameter(Parameter parameter) {
- if (nuParameter != null) removeVariable(nuParameter);
- nuParameter = parameter;
- if (nuParameter != null) addVariable(nuParameter);
+ public void setRelativeRateParameter(Parameter nu) {
+ this.nuParameter = nu;
}
// *****************************************************************
@@ -273,6 +262,7 @@ private void calculateCategoryRates() {
final double a = shapeParameter.getParameterValue(0);
double mean = 0.0;
+ double sum = 0.0;
final int gammaCatCount = categoryCount - cat;
for (int i = 0; i < gammaCatCount; i++) {
@@ -285,14 +275,22 @@ private void calculateCategoryRates() {
mean += categoryRates[i + cat];
- categoryProportions[i + cat] = propVariable / gammaCatCount;
+ if (categoryWidthParameter != null && categoryWidthType == CategoryWidthType.GEOMETRIC && i > 0) {
+ categoryProportions[i + cat] = categoryProportions[i + cat - 1] * (1.0 + categoryWidthParameter.getParameterValue(0));
+ } else if (categoryWidthParameter != null && categoryWidthType == CategoryWidthType.FASTEST &&
+ i == (gammaCatCount - 1)) {
+ categoryProportions[i + cat] = (1.0 + categoryWidthParameter.getParameterValue(0));
+ } else {
+ categoryProportions[i + cat] = 1.0;
+ }
+ sum += categoryProportions[i + cat];
}
mean = (propVariable * mean) / gammaCatCount;
for (int i = 0; i < gammaCatCount; i++) {
-
categoryRates[i + cat] /= mean;
+ categoryProportions[i + cat] /= sum;
}
} else {
categoryRates[cat] = 1.0 / propVariable;
@@ -309,10 +307,6 @@ private void calculateCategoryRates() {
ratesKnown = true;
}
- public boolean hasInvariantSites() {
- return invarParameter != null;
- }
-
// *****************************************************************
// Interface ModelComponent
// *****************************************************************
@@ -327,6 +321,8 @@ protected final void handleVariableChangedEvent(Variable variable, int index, Pa
ratesKnown = false;
} else if (variable == invarParameter) {
ratesKnown = false;
+ } else if (variable == categoryWidthParameter) {
+ ratesKnown = false;
} else if (variable == nuParameter) {
ratesKnown = false; // MAS: I changed this because the rate parameter can affect the categories if the parameter is in siteModel and not clockModel
} else {
@@ -384,6 +380,10 @@ public double getStatisticValue(int dim) {
*/
private Parameter invarParameter;
+ private Parameter categoryWidthParameter;
+
+ private CategoryWidthType categoryWidthType = null;
+
private boolean ratesKnown;
private int categoryCount;
@@ -417,7 +417,7 @@ public String getDescription() {
}
public List getCitations() {
- if (getAlphaParameter() != null) {
+ if (shapeParameter != null) {
return Collections.singletonList(CITATION);
} else {
return Collections.emptyList();
@@ -437,4 +437,5 @@ public List getCitations() {
);
private SubstitutionModel substitutionModel;
+
}
\ No newline at end of file
diff --git a/src/dr/evomodel/substmodel/MarkovModulatedFrequencyModel.java b/src/dr/evomodel/substmodel/MarkovModulatedFrequencyModel.java
index b44bf4b97c..87035f728d 100644
--- a/src/dr/evomodel/substmodel/MarkovModulatedFrequencyModel.java
+++ b/src/dr/evomodel/substmodel/MarkovModulatedFrequencyModel.java
@@ -47,7 +47,8 @@
public class MarkovModulatedFrequencyModel extends FrequencyModel {
- MarkovModulatedFrequencyModel(String name, List freqModels, Parameter switchingRates) {
+ MarkovModulatedFrequencyModel(String name, List freqModels, Parameter switchingRates,
+ Parameter relativeWeight) {
super(name);
this.freqModels = freqModels;
int freqCount = 0;
@@ -72,6 +73,12 @@ public class MarkovModulatedFrequencyModel extends FrequencyModel {
DoubleMatrix2D d = new DenseDoubleMatrix2D(numBaseModel, numBaseModel);
d.set(0, 0, 1.0);
+
+ this.relativeWeight = relativeWeight;
+ if (relativeWeight != null) {
+ addVariable(relativeWeight);
+ }
+ checkRelativeWeight();
}
public void setFrequency(int i, double value) {
@@ -81,7 +88,13 @@ public void setFrequency(int i, double value) {
public double getFrequency(int index) {
int whichModel = index / stateCount;
int whichState = index % stateCount;
- double relativeFreq = freqModels.get(whichModel).getFrequency(whichState) / numBaseModel;
+ double relativeFreq = freqModels.get(whichModel).getFrequency(whichState);
+
+ if (relativeWeight != null) {
+ relativeFreq *= relativeWeight.getParameterValue(whichModel);
+ } else {
+ relativeFreq /= numBaseModel;
+ }
// Scale by stationary distribution over hidden classes
if (numBaseModel > 1) {
@@ -168,6 +181,18 @@ protected void handleVariableChangedEvent(Variable variable, int index, Paramete
}
}
+ private void checkRelativeWeight() {
+ if (relativeWeight != null) {
+ double sum = 0.0;
+ for (double x : relativeWeight.getParameterValues()) {
+ sum += x;
+ }
+ if (sum != 1.0) {
+ throw new IllegalArgumentException("Relative weights must sum to 1.0");
+ }
+ }
+ }
+
protected void handleModelChangedEvent(Model model, Object object, int index) {
fireModelChanged();
}
@@ -186,6 +211,7 @@ public Parameter getFrequencyParameter() {
private final int totalFreqCount;
private final int stateCount;
private final Parameter switchingRates;
+ private final Parameter relativeWeight;
private double[] baseStationaryDistribution;
private double[] storedBaseStationaryDistribution;
diff --git a/src/dr/evomodel/substmodel/MarkovModulatedSubstitutionModel.java b/src/dr/evomodel/substmodel/MarkovModulatedSubstitutionModel.java
index bbb031cfb3..51f215a2be 100644
--- a/src/dr/evomodel/substmodel/MarkovModulatedSubstitutionModel.java
+++ b/src/dr/evomodel/substmodel/MarkovModulatedSubstitutionModel.java
@@ -76,7 +76,7 @@ public MarkovModulatedSubstitutionModel(String name,
Parameter switchingRates,
DataType dataType,
EigenSystem eigenSystem) {
- this(name, baseModels, switchingRates, dataType, eigenSystem, null, false, null);
+ this(name, baseModels, switchingRates, dataType, eigenSystem, null, false, null, null);
}
public MarkovModulatedSubstitutionModel(String name,
@@ -86,7 +86,8 @@ public MarkovModulatedSubstitutionModel(String name,
EigenSystem eigenSystem,
Parameter rateScalar,
boolean geometricRates,
- SiteRateModel gammaRateModel) {
+ SiteRateModel gammaRateModel,
+ Parameter relativeWeights) {
// super(name, dataType, null, eigenSystem);
super(name, dataType, null, null);
@@ -121,7 +122,7 @@ public MarkovModulatedSubstitutionModel(String name,
}
// This constructor also checks that all models have the same base stateCount
- freqModel = new MarkovModulatedFrequencyModel("mm", freqModels, switchingRates);
+ freqModel = new MarkovModulatedFrequencyModel("mm", freqModels, switchingRates, relativeWeights);
addModel(freqModel);
if (stateCount != stateSizes) {
diff --git a/src/dr/evomodel/substmodel/OldGLMSubstitutionModel.java b/src/dr/evomodel/substmodel/OldGLMSubstitutionModel.java
index fd3a75caec..9ba19bffef 100644
--- a/src/dr/evomodel/substmodel/OldGLMSubstitutionModel.java
+++ b/src/dr/evomodel/substmodel/OldGLMSubstitutionModel.java
@@ -94,7 +94,7 @@ public LogColumn[] getColumns() {
public double getLogLikelihood() {
double logL = super.getLogLikelihood();
if (logL == 0 &&
- BayesianStochasticSearchVariableSelection.Utils.connectedAndWellConditioned(testProbabilities,this)) { // Also check that graph is connected
+ BayesianStochasticSearchVariableSelection.Utils.connectedAndWellConditioned(testProbabilities,this)) { // Also check that graph is connected
return 0;
}
return Double.NEGATIVE_INFINITY;
@@ -123,6 +123,7 @@ public ParameterReplaceableSubstitutionModel factory(List oldParamete
@Override
public WrappedMatrix getInfinitesimalDifferentialMatrix(DifferentialMassProvider.DifferentialWrapper.WrtParameter wrt) {
+ // TODO all instantiations of this function currently do the same thing; remove duplication
return DifferentiableSubstitutionModelUtil.getInfinitesimalDifferentialMatrix(wrt, this);
}
@@ -179,8 +180,18 @@ public void setupDifferentialRates(double[] differentialRates, double[] Q, doubl
}
}
+// final double chainRule = getChainRule();
+// double[][] design = glm.getX(effect);
+//
+// for (int i = 0; i < relativeRates.length; ++i) {
+// differentialRates[i] = design[i][dim] / normalizingConstant * chainRule;
+// }
}
+// double getChainRule() {
+// return Math.exp(parameter.getParameterValue(dim));
+// }
+
private int index(int i, int j) {
return i * stateCount + j;
}
@@ -196,10 +207,21 @@ public DifferentialMassProvider.DifferentialWrapper.WrtParameter factory(Paramet
return new WrtOldGLMSubstitutionModelParameter(glm, effectIndex, dim, stateCount);
}
+// @Override
+// public DifferentialMassProvider.DifferentialWrapper.WrtParameter factory(Parameter parameter, int dim) {
+// for (int i = 0; i < glm.getNumberOfFixedEffects(); ++i) {
+// Parameter effect = glm.getFixedEffect(i);
+// if (parameter == effect) {
+// return new WrtGlmCoefficient(effect, i, dim);
+// }
+// }
+// throw new RuntimeException("Parameter not found");
+// }
+
@Override
public void setupDifferentialRates(DifferentialMassProvider.DifferentialWrapper.WrtParameter wrt, double[] differentialRates, double normalizingConstant) {
final double[] Q = new double[stateCount * stateCount];
- getInfinitesimalMatrix(Q);
+ getInfinitesimalMatrix(Q); // TODO These are large; should cache
wrt.setupDifferentialRates(differentialRates, Q, normalizingConstant);
}
@@ -211,15 +233,19 @@ public void setupDifferentialFrequency(DifferentialMassProvider.DifferentialWrap
@Override
public double getWeightedNormalizationGradient(DifferentialMassProvider.DifferentialWrapper.WrtParameter wrt, double[][] differentialMassMatrix, double[] differentialFrequencies) {
double derivative = 0;
- double[] frequencies = getFrequencyModel().getFrequencies();
- for (int i = 0; i < stateCount; i++) {
- double currentRow = 0;
- for (int j = 0; j < stateCount; j++) {
- if (i != j) {
- currentRow +=differentialMassMatrix[i][j];
- }
- }
- derivative += currentRow * frequencies[i];
+// double[] frequencies = getFrequencyModel().getFrequencies();
+// for (int i = 0; i < stateCount; i++) {
+// double currentRow = 0;
+// for (int j = 0; j < stateCount; j++) {
+// if (i != j) {
+// currentRow +=differentialMassMatrix[i][j];
+// }
+// }
+// derivative += currentRow * frequencies[i];
+// }
+// return derivative;
+ for (int i = 0; i < stateCount; ++i) {
+ derivative -= differentialMassMatrix[i][i] * getFrequencyModel().getFrequency(i);
}
return derivative;
}
diff --git a/src/dr/evomodel/tree/AgeStatistic.java b/src/dr/evomodel/tree/AgeStatistic.java
new file mode 100644
index 0000000000..0bf892c579
--- /dev/null
+++ b/src/dr/evomodel/tree/AgeStatistic.java
@@ -0,0 +1,82 @@
+/*
+ * TMRCAStatistic.java
+ *
+ * Copyright (c) 2002-2015 Alexei Drummond, Andrew Rambaut and Marc Suchard
+ *
+ * This file is part of BEAST.
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership and licensing.
+ *
+ * BEAST is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * BEAST is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with BEAST; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+
+package dr.evomodel.tree;
+
+import dr.evolution.tree.NodeRef;
+import dr.evolution.tree.Tree;
+import dr.evolution.tree.TreeUtils;
+import dr.evolution.util.Taxon;
+import dr.evolution.util.TaxonList;
+import dr.inference.model.Statistic;
+
+import java.util.Set;
+
+/**
+ * A statistic that calculates the age (absolute time) from a height
+ *
+ * @author Andrew Rambaut
+ * @version $Id: $
+ */
+public class AgeStatistic extends Statistic.Abstract {
+
+ public AgeStatistic(String name, Statistic heightStatistic) {
+ super(name);
+ this.heightStatistic = heightStatistic;
+ if (Taxon.getMostRecentDate() != null) {
+ isBackwards = Taxon.getMostRecentDate().isBackwards();
+ mostRecentTipTime = Taxon.getMostRecentDate().getAbsoluteTimeValue();
+ } else {
+ // give node heights or taxa don't have dates
+ mostRecentTipTime = Double.NaN;
+ isBackwards = false;
+ }
+ }
+
+ public int getDimension() {
+ return 1;
+ }
+
+ /**
+ * @return the height of the MRCA node.
+ */
+ public double getStatisticValue(int dim) {
+
+ if (!Double.isNaN(mostRecentTipTime)) {
+ if (isBackwards) {
+ return mostRecentTipTime + heightStatistic.getStatisticValue(dim);
+ } else {
+ return mostRecentTipTime - heightStatistic.getStatisticValue(dim);
+ }
+ } else {
+ return Double.NaN;
+ }
+ }
+
+ private Statistic heightStatistic = null;
+ private final double mostRecentTipTime;
+ private final boolean isBackwards;
+
+}
diff --git a/src/dr/evomodel/tree/BranchLengthStatistic.java b/src/dr/evomodel/tree/BranchLengthStatistic.java
new file mode 100644
index 0000000000..74c6fdfe14
--- /dev/null
+++ b/src/dr/evomodel/tree/BranchLengthStatistic.java
@@ -0,0 +1,83 @@
+/*
+ * TMRCAStatistic.java
+ *
+ * Copyright (c) 2002-2015 Alexei Drummond, Andrew Rambaut and Marc Suchard
+ *
+ * This file is part of BEAST.
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership and licensing.
+ *
+ * BEAST is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * BEAST is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with BEAST; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+
+package dr.evomodel.tree;
+
+import dr.evolution.tree.NodeRef;
+import dr.evolution.tree.Tree;
+import dr.evolution.tree.TreeUtils;
+import dr.evolution.util.Taxon;
+import dr.evolution.util.TaxonList;
+
+import java.util.Set;
+
+/**
+ * A statistic that extracts the length of the stem branch of a set of taxa
+ *
+ * @author Andrew Rambaut
+ * @version $Id:$
+ */
+public class BranchLengthStatistic extends TreeStatistic {
+
+ public BranchLengthStatistic(String name, Tree tree, TaxonList taxa)
+ throws TreeUtils.MissingTaxonException {
+ super(name);
+ this.tree = tree;
+ if (taxa != null) {
+ this.leafSet = TreeUtils.getLeavesForTaxa(tree, taxa);
+ } else {
+ throw new IllegalArgumentException("taxa cannot be null");
+ }
+ }
+
+ public void setTree(Tree tree) {
+ this.tree = tree;
+ }
+
+ public Tree getTree() {
+ return tree;
+ }
+
+ public int getDimension() {
+ return 1;
+ }
+
+ /**
+ * @return the height of the MRCA node.
+ */
+ public double getStatisticValue(int dim) {
+ NodeRef node = TreeUtils.getCommonAncestorNode(tree, leafSet);
+
+ if (node == null) {
+ throw new RuntimeException("No node found that is MRCA of " + leafSet);
+ }
+
+ return tree.getBranchLength(node);
+ }
+
+ private Tree tree = null;
+ private Set leafSet = null;
+
+}
diff --git a/src/dr/evomodel/treedatalikelihood/BeagleDataLikelihoodDelegate.java b/src/dr/evomodel/treedatalikelihood/BeagleDataLikelihoodDelegate.java
index 232644ccd2..8110f036b6 100644
--- a/src/dr/evomodel/treedatalikelihood/BeagleDataLikelihoodDelegate.java
+++ b/src/dr/evomodel/treedatalikelihood/BeagleDataLikelihoodDelegate.java
@@ -377,7 +377,7 @@ public BeagleDataLikelihoodDelegate(Tree tree,
benchmarkFlags = BeagleBenchmarkFlag.SCALING_DYNAMIC.getMask();
}
- logger.info("\nRunning benchmarks to automatically select fastest BEAGLE resource for analysis or partition... ");
+ logger.info("\t\tRunning benchmarks to automatically select fastest BEAGLE resource for analysis or partition... ");
List benchmarkedResourceDetails =
BeagleFactory.getBenchmarkedResourceDetails(
@@ -448,8 +448,20 @@ public BeagleDataLikelihoodDelegate(Tree tree,
instanceFlags = instanceDetails.getFlags();
- if (IS_THREAD_COUNT_COMPATIBLE() && threadCount > 1) {
- beagle.setCPUThreadCount(threadCount);
+ if ((instanceFlags & BeagleFlag.THREADING_CPP.getMask()) != 0) {
+ if (IS_THREAD_COUNT_COMPATIBLE() || threadCount != 0) {
+ if (threadCount > 0) {
+ beagle.setCPUThreadCount(threadCount);
+ logger.info(" Using " + threadCount + " threads for CPU.");
+ } else { // if no thread_count is specified then this will be -1 so put no upper bound on threads
+ logger.info(" Using default thread count for CPU.");
+ // this is just intended to remove the cap on number of threads so BEAGLE will
+ // make its own decision (for better or worse).
+ beagle.setCPUThreadCount(1000);
+ }
+ } else {
+ logger.info(" BEAGLE threading turned off (or unavailable) for CPU.");
+ }
}
if (patternList instanceof UncertainSiteList) { // TODO Remove
@@ -461,12 +473,12 @@ public BeagleDataLikelihoodDelegate(Tree tree,
// }
//add in logger info for preOrder traversal
- logger.info(" " + (settings.usePreOrder ? "Using" : "Ignoring") + " preOrder partials in tree likelihood.");
- logger.info(" " + (useAmbiguities ? "Using" : "Ignoring") + " ambiguities in tree likelihood.");
- logger.info(" With " + patternList.getPatternCount() + " unique site patterns.");
+ logger.info(" " + (settings.usePreOrder ? "Using" : "Ignoring") + " preOrder partials in tree likelihood.");
+ logger.info(" " + (useAmbiguities ? "Using" : "Ignoring") + " ambiguities in tree likelihood.");
+ logger.info(" With " + patternList.getPatternCount() + " unique site patterns.");
if (patternList.areUncertain() && !useAmbiguities) {
- logger.info(" WARNING: Uncertain site patterns will be ignored.");
+ logger.info(" WARNING: Uncertain site patterns will be ignored.");
}
for (int i = 0; i < tipCount; i++) {
@@ -488,13 +500,13 @@ public BeagleDataLikelihoodDelegate(Tree tree,
beagle.setPatternWeights(patternWeights);
- String rescaleMessage = " Using rescaling scheme : " + this.rescalingScheme.getText();
+ String rescaleMessage = " Using rescaling scheme : " + this.rescalingScheme.getText();
if (this.rescalingScheme == PartialsRescalingScheme.AUTO &&
resourceDetails != null &&
(resourceDetails.getFlags() & BeagleFlag.SCALING_AUTO.getMask()) == 0) {
// If auto scaling in BEAGLE is not supported then do it here
this.rescalingScheme = PartialsRescalingScheme.DYNAMIC;
- rescaleMessage = " Auto rescaling not supported in BEAGLE, using : " + this.rescalingScheme.getText();
+ rescaleMessage = " Auto rescaling not supported in BEAGLE, using : " + this.rescalingScheme.getText();
}
boolean parenthesis = false;
if (this.rescalingScheme == PartialsRescalingScheme.DYNAMIC) {
diff --git a/src/dr/evomodel/treedatalikelihood/TreeDataLikelihood.java b/src/dr/evomodel/treedatalikelihood/TreeDataLikelihood.java
index 4482b586f3..29bd3d65bd 100644
--- a/src/dr/evomodel/treedatalikelihood/TreeDataLikelihood.java
+++ b/src/dr/evomodel/treedatalikelihood/TreeDataLikelihood.java
@@ -63,7 +63,7 @@ public TreeDataLikelihood(DataLikelihoodDelegate likelihoodDelegate,
final Logger logger = Logger.getLogger("dr.evomodel");
- logger.info("\nUsing TreeDataLikelihood");
+ logger.info("\nCreating TreeDataLikelihood");
this.likelihoodDelegate = likelihoodDelegate;
addModel(likelihoodDelegate);
@@ -79,7 +79,7 @@ public TreeDataLikelihood(DataLikelihoodDelegate likelihoodDelegate,
this.branchRateModel = branchRateModel;
if (!(branchRateModel instanceof DefaultBranchRateModel)) {
- logger.info(" Branch rate model used: " + branchRateModel.getModelName());
+ logger.info(" Branch rate model: " + branchRateModel.getModelName());
}
addModel(this.branchRateModel);
diff --git a/src/dr/evomodel/treelikelihood/BeagleTreeLikelihood.java b/src/dr/evomodel/treelikelihood/BeagleTreeLikelihood.java
index 15e2afd514..f3cd2cd036 100644
--- a/src/dr/evomodel/treelikelihood/BeagleTreeLikelihood.java
+++ b/src/dr/evomodel/treelikelihood/BeagleTreeLikelihood.java
@@ -434,8 +434,12 @@ public BeagleTreeLikelihood(PatternList patternList,
logger.info(" No external BEAGLE resources available, or resource list/requirements not met, using Java implementation");
}
- if (IS_THREAD_COUNT_COMPATIBLE() && threadCount > 1) {
- beagle.setCPUThreadCount(threadCount);
+ if (IS_THREAD_COUNT_COMPATIBLE()) {
+ if (threadCount > 0) {
+ beagle.setCPUThreadCount(threadCount);
+ } else { // if no thread_count is specified then this will be -1 so put no upper bound on threads
+ beagle.setCPUThreadCount(Integer.MAX_VALUE);
+ }
}
logger.info(" " + (useAmbiguities ? "Using" : "Ignoring") + " ambiguities in tree likelihood.");
diff --git a/src/dr/evomodelxml/branchratemodel/LocalClockModelParser.java b/src/dr/evomodelxml/branchratemodel/LocalClockModelParser.java
index 164865a01b..78794827b9 100644
--- a/src/dr/evomodelxml/branchratemodel/LocalClockModelParser.java
+++ b/src/dr/evomodelxml/branchratemodel/LocalClockModelParser.java
@@ -46,6 +46,7 @@ public class LocalClockModelParser extends AbstractXMLObjectParser {
public static final String CLADE = "clade";
public static final String INCLUDE_STEM = "includeStem";
public static final String STEM_PROPORTION = "stemProportion";
+ public static final String STEM_TIME = "stemTime";
public static final String EXCLUDE_CLADE = "excludeClade";
public static final String EXTERNAL_BRANCHES = "externalBranches";
public static final String TRUNK = "trunk";
@@ -93,18 +94,42 @@ public Object parseXMLObject(XMLObject xo) throws XMLParseException {
}
boolean excludeClade = false;
- double stemProportion = 0.0;
+ Parameter stemParameter = null;
+ boolean stemAsTime = false;
if (xoc.hasAttribute(INCLUDE_STEM)) {
// if includeStem=true then assume it is the whole stem
- stemProportion = xoc.getBooleanAttribute(INCLUDE_STEM) ? 1.0 : 0.0;
+ stemParameter = new Parameter.Default(xoc.getBooleanAttribute(INCLUDE_STEM) ? 1.0 : 0.0);
}
if (xoc.hasAttribute(STEM_PROPORTION)) {
- stemProportion = xoc.getDoubleAttribute(STEM_PROPORTION);
- if (stemProportion < 0.0 || stemProportion > 1.0) {
+ double stemValue = xoc.getDoubleAttribute(STEM_PROPORTION);
+ if (stemValue < 0.0 || stemValue > 1.0) {
throw new XMLParseException("A stem proportion should be between 0, 1");
}
+ stemParameter = new Parameter.Default(stemValue);
+ }
+ if (xoc.hasAttribute(STEM_TIME)) {
+ double stemValue = xoc.getDoubleAttribute(STEM_TIME);
+ if (stemValue < 0.0) {
+ throw new XMLParseException("A stem time should be >= 0");
+ }
+ stemParameter = new Parameter.Default(stemValue);
+ stemAsTime = true;
+ }
+
+ if (xoc.hasChildNamed(STEM_PROPORTION)) {
+ stemParameter = (Parameter) xoc.getElementFirstChild(STEM_PROPORTION);
+ if (stemParameter.getParameterValue(0) < 0.0 || stemParameter.getParameterValue(0) > 1.0) {
+ throw new XMLParseException("A stem proportion should be between 0, 1");
+ }
+ }
+ if (xoc.hasChildNamed(STEM_TIME)) {
+ stemParameter = (Parameter) xoc.getElementFirstChild(STEM_TIME);
+ if (stemParameter.getParameterValue(0) < 0.0) {
+ throw new XMLParseException("A stem time should be >= 0");
+ }
+ stemAsTime = true;
}
if (xoc.hasAttribute(EXCLUDE_CLADE)) {
@@ -113,9 +138,9 @@ public Object parseXMLObject(XMLObject xo) throws XMLParseException {
try {
if (branchRates != null) {
- localClockModel.addCladeClock(taxonList, branchRates, relative, stemProportion, excludeClade);
+ localClockModel.addCladeClock(taxonList, branchRates, relative, stemParameter, stemAsTime, excludeClade);
} else {
- localClockModel.addCladeClock(taxonList, rateParameter, relative, stemProportion, excludeClade);
+ localClockModel.addCladeClock(taxonList, rateParameter, relative, stemParameter, stemAsTime, excludeClade);
}
} catch (TreeUtils.MissingTaxonException mte) {
@@ -204,8 +229,16 @@ public XMLSyntaxRule[] getSyntaxRules() {
new ElementRule(CLADE,
new XMLSyntaxRule[]{
AttributeRule.newBooleanRule(RELATIVE, true),
- AttributeRule.newBooleanRule(INCLUDE_STEM, true, "determines whether or not the stem branch above this clade is included in the siteModel (default false)."),
- AttributeRule.newDoubleRule(STEM_PROPORTION, true, "proportion of stem to include in clade rate (default 0)."),
+ new XORRule(
+ new XMLSyntaxRule[]{
+ AttributeRule.newBooleanRule(INCLUDE_STEM, true, "determines whether or not the stem branch above this clade is included in the siteModel (default false)."),
+ AttributeRule.newDoubleRule(STEM_PROPORTION, true, "proportion of stem to include in clade rate (default 0)."),
+ new ElementRule(STEM_PROPORTION, Parameter.class, "A parameter for the proportion of stem to include in clade rate (0 - 1)", false),
+ AttributeRule.newDoubleRule(STEM_TIME, true, "time within the stem to include in clade rate (default 0)."),
+ new ElementRule(STEM_TIME, Parameter.class, "A parameter for the time of stem to include in clade rate", false)
+ },
+ true
+ ),
AttributeRule.newBooleanRule(EXCLUDE_CLADE, true, "determines whether to exclude actual branches of the clade from the siteModel (default false)."),
new ElementRule(Taxa.class, "A set of taxa which defines a clade to apply a different site model to"),
new XORRule(
diff --git a/src/dr/evomodelxml/coalescent/CoalescentSimulatorParser.java b/src/dr/evomodelxml/coalescent/CoalescentSimulatorParser.java
index 25988a54f3..28fe5d5233 100644
--- a/src/dr/evomodelxml/coalescent/CoalescentSimulatorParser.java
+++ b/src/dr/evomodelxml/coalescent/CoalescentSimulatorParser.java
@@ -82,7 +82,7 @@ public Object parseXMLObject(XMLObject xo) throws XMLParseException {
if (taxonLists.size() == 0) {
if (subtrees.size() == 1) {
return subtrees.get(0);
- } if (constraintsTree==null){
+ } else if (subtrees.size() == 0 && constraintsTree==null) {
throw new XMLParseException("Expected at least one taxonList or two subtrees or a constraints tree in "
+ getParserName() + " element.");
}
diff --git a/src/dr/evomodelxml/coalescent/GMRFSkyrideGradientParser.java b/src/dr/evomodelxml/coalescent/GMRFSkyrideGradientParser.java
index d02519e65e..e8abb55726 100644
--- a/src/dr/evomodelxml/coalescent/GMRFSkyrideGradientParser.java
+++ b/src/dr/evomodelxml/coalescent/GMRFSkyrideGradientParser.java
@@ -41,8 +41,8 @@
*/
public class GMRFSkyrideGradientParser extends AbstractXMLObjectParser {
- private static final String NAME = "gmrfSkyrideGradient";
- private static final String WRT_PARAMETER = "wrtParameter";
+ public static final String NAME = "gmrfSkyrideGradient";
+ public static final String WRT_PARAMETER = "wrtParameter";
private static final String COALESCENT_INTERVAL = "coalescentInterval";
private static final String NODE_HEIGHTS = "nodeHeights";
diff --git a/src/dr/evomodelxml/coalescent/TreeIntervalsParser.java b/src/dr/evomodelxml/coalescent/TreeIntervalsParser.java
index 1019224114..cfa118a803 100644
--- a/src/dr/evomodelxml/coalescent/TreeIntervalsParser.java
+++ b/src/dr/evomodelxml/coalescent/TreeIntervalsParser.java
@@ -2,14 +2,19 @@
import dr.evolution.tree.Tree;
import dr.evolution.tree.TreeUtils;
+import dr.evolution.util.TaxonList;
import dr.evomodel.coalescent.TreeIntervals;
import dr.evomodel.tree.TreeModel;
import dr.xml.*;
+import java.util.ArrayList;
+import java.util.List;
+
public class TreeIntervalsParser extends AbstractXMLObjectParser{
public static final String TREE_INTERVALS = "treeIntervals";
- public static final String TREE = "tree";
+ public static final String INCLUDE = "include";
+ public static final String EXCLUDE = "exclude";
public String getParserName() {
return TREE_INTERVALS;
@@ -19,8 +24,23 @@ public Object parseXMLObject(XMLObject xo) throws XMLParseException {
Tree tree = (Tree) xo.getChild(Tree.class);
+ TaxonList includeSubtree = null;
+
+ if (xo.hasChildNamed(INCLUDE)) {
+ includeSubtree = (TaxonList) xo.getElementFirstChild(INCLUDE);
+ }
+
+ List excludeSubtrees = new ArrayList<>();
+
+ if (xo.hasChildNamed(EXCLUDE)) {
+ XMLObject cxo = xo.getChild(EXCLUDE);
+ for (int i = 0; i < cxo.getChildCount(); i++) {
+ excludeSubtrees.add((TaxonList) cxo.getChild(i));
+ }
+ }
+
try {
- return new TreeIntervals(tree, null, null);
+ return new TreeIntervals(tree, includeSubtree, excludeSubtrees);
} catch (TreeUtils.MissingTaxonException mte) {
throw new XMLParseException("Taxon, " + mte + ", in " + getParserName() + " was not found in the tree.");
}
diff --git a/src/dr/evomodelxml/siteratemodel/GammaSiteModelParser.java b/src/dr/evomodelxml/siteratemodel/GammaSiteModelParser.java
index 0b890f0449..721f9d564c 100644
--- a/src/dr/evomodelxml/siteratemodel/GammaSiteModelParser.java
+++ b/src/dr/evomodelxml/siteratemodel/GammaSiteModelParser.java
@@ -55,6 +55,10 @@ public class GammaSiteModelParser extends AbstractXMLObjectParser {
public static final String GAMMA_SHAPE = "gammaShape";
public static final String GAMMA_CATEGORIES = "gammaCategories";
public static final String PROPORTION_INVARIANT = "proportionInvariant";
+ public static final String CATEGORY_WIDTH = "categoryWidth";
+ public static final String TYPE = "type";
+ public static final String FASTEST = "fastest";
+ public static final String GEOMETRIC = "geometric";
public String getParserName() {
return SITE_MODEL;
@@ -102,13 +106,30 @@ public Object parseXMLObject(XMLObject xo) throws XMLParseException {
msg += "\n initial proportion of invariant sites = " + invarParam.getParameterValue(0);
}
+ Parameter categoryWidthParameter = null;
+ GammaSiteRateModel.CategoryWidthType type = null;
+ if (xo.hasChildNamed(CATEGORY_WIDTH)) {
+ categoryWidthParameter = (Parameter) xo.getElementFirstChild(CATEGORY_WIDTH);
+ String typeString = xo.getChild(CATEGORY_WIDTH).getStringAttribute(TYPE);
+ try {
+ type = GammaSiteRateModel.CategoryWidthType.valueOf(typeString.toUpperCase());
+ if (type == GammaSiteRateModel.CategoryWidthType.FASTEST) {
+ msg += "\n initial proportion of fastest sites = " + categoryWidthParameter.getParameterValue(0);
+ } else {
+ msg += "\n initial factor for increasing category width = " + categoryWidthParameter.getParameterValue(0);
+ }
+ } catch (IllegalArgumentException eae) {
+ throw new XMLParseException("Unknown category width type: " + typeString);
+ }
+ }
+
if (msg.length() > 0) {
Logger.getLogger("dr.evomodel").info("\nCreating site rate model: " + msg);
} else {
Logger.getLogger("dr.evomodel").info("\nCreating site rate model.");
}
- GammaSiteRateModel siteRateModel = new GammaSiteRateModel(SITE_MODEL, muParam, muWeight, shapeParam, catCount, invarParam);
+ GammaSiteRateModel siteRateModel = new GammaSiteRateModel(SITE_MODEL, muParam, muWeight, shapeParam, catCount, invarParam, categoryWidthParameter, type);
if (xo.hasChildNamed(SUBSTITUTION_MODEL)) {
@@ -167,6 +188,11 @@ public XMLSyntaxRule[] getSyntaxRules() {
new ElementRule(PROPORTION_INVARIANT, new XMLSyntaxRule[]{
new ElementRule(Parameter.class)
+ }, true),
+
+ new ElementRule(CATEGORY_WIDTH, new XMLSyntaxRule[]{
+ AttributeRule.newStringRule(TYPE, false),
+ new ElementRule(Parameter.class)
}, true)
};
diff --git a/src/dr/evomodelxml/substmodel/MarkovModulatedSubstitutionModelParser.java b/src/dr/evomodelxml/substmodel/MarkovModulatedSubstitutionModelParser.java
index 2f557bfad2..14bb794ac8 100644
--- a/src/dr/evomodelxml/substmodel/MarkovModulatedSubstitutionModelParser.java
+++ b/src/dr/evomodelxml/substmodel/MarkovModulatedSubstitutionModelParser.java
@@ -49,6 +49,7 @@ public class MarkovModulatedSubstitutionModelParser extends AbstractXMLObjectPar
public static final String RATE_SCALAR = "rateScalar";
public static final String GEOMETRIC_RATES = "geometricRates";
public static final String RENORMALIZE = "renormalize";
+ private static final String RELATIVE_WEIGHTS = "relativeWeights";
public String getParserName() {
return MARKOV_MODULATED_MODEL;
@@ -85,8 +86,13 @@ public Object parseXMLObject(XMLObject xo) throws XMLParseException {
}
}
+ Parameter relativeWeights = null;
+ if (xo.hasChildNamed(RELATIVE_WEIGHTS)) {
+ relativeWeights = (Parameter) xo.getElementFirstChild(RELATIVE_WEIGHTS);
+ }
+
MarkovModulatedSubstitutionModel mmsm = new MarkovModulatedSubstitutionModel(xo.getId(), substModels, switchingRates, dataType, null,
- rateScalar, geometricRates, siteRateModel);
+ rateScalar, geometricRates, siteRateModel, relativeWeights);
if (xo.getAttribute(RENORMALIZE, false)) {
mmsm.setNormalization(true);
@@ -124,7 +130,8 @@ public XMLSyntaxRule[] getSyntaxRules() {
AttributeRule.newBooleanRule(RENORMALIZE, true),
new ElementRule(RATE_SCALAR,
new XMLSyntaxRule[]{new ElementRule(Parameter.class)}, true),
-
+ new ElementRule(RELATIVE_WEIGHTS,
+ new XMLSyntaxRule[]{new ElementRule(Parameter.class)}, true),
new ElementRule(SiteRateModel.class, true),
};
}
diff --git a/src/dr/evomodelxml/tree/AgeStatisticParser.java b/src/dr/evomodelxml/tree/AgeStatisticParser.java
new file mode 100644
index 0000000000..1df12c7887
--- /dev/null
+++ b/src/dr/evomodelxml/tree/AgeStatisticParser.java
@@ -0,0 +1,82 @@
+/*
+ * TMRCAStatisticParser.java
+ *
+ * Copyright (c) 2002-2015 Alexei Drummond, Andrew Rambaut and Marc Suchard
+ *
+ * This file is part of BEAST.
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership and licensing.
+ *
+ * BEAST is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * BEAST is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with BEAST; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+
+package dr.evomodelxml.tree;
+
+import dr.evolution.tree.Tree;
+import dr.evolution.tree.TreeUtils;
+import dr.evolution.util.Taxa;
+import dr.evolution.util.TaxonList;
+import dr.evomodel.tree.AgeStatistic;
+import dr.evomodel.tree.TMRCAStatistic;
+import dr.inference.model.Statistic;
+import dr.xml.*;
+
+/**
+ *
+ * Converts a statistic or parameter into absolute age:
+ *
+ *
+ *
+ *
+ * @author Andrew Rambaut
+ */
+public class AgeStatisticParser extends AbstractXMLObjectParser {
+
+ public static final String AGE_STATISTIC = "ageStatistic";
+
+
+ public String getParserName() {
+ return AGE_STATISTIC;
+ }
+
+ public Object parseXMLObject(XMLObject xo) throws XMLParseException {
+
+ String name = xo.getAttribute(Statistic.NAME, xo.getId());
+ Statistic heightStatistic = (Statistic) xo.getChild(Statistic.class);
+ return new AgeStatistic(name, heightStatistic);
+ }
+
+ //************************************************************************
+ // AbstractXMLObjectParser implementation
+ //************************************************************************
+
+ public String getParserDescription() {
+ return "A statistic that converts a height statistic into an absolute age using the date of the most recent tip. ";
+ }
+
+ public Class getReturnType() {
+ return AgeStatistic.class;
+ }
+
+ public XMLSyntaxRule[] getSyntaxRules() {
+ return rules;
+ }
+
+ private final XMLSyntaxRule[] rules = {
+ new ElementRule(Statistic.class)
+ };
+
+}
diff --git a/src/dr/evomodelxml/tree/BranchLengthStatisticParser.java b/src/dr/evomodelxml/tree/BranchLengthStatisticParser.java
new file mode 100644
index 0000000000..81032d5ab1
--- /dev/null
+++ b/src/dr/evomodelxml/tree/BranchLengthStatisticParser.java
@@ -0,0 +1,102 @@
+/*
+ * TMRCAStatisticParser.java
+ *
+ * Copyright (c) 2002-2015 Alexei Drummond, Andrew Rambaut and Marc Suchard
+ *
+ * This file is part of BEAST.
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership and licensing.
+ *
+ * BEAST is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * BEAST is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with BEAST; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+
+package dr.evomodelxml.tree;
+
+import dr.evolution.tree.Tree;
+import dr.evolution.tree.TreeUtils;
+import dr.evolution.util.Taxa;
+import dr.evolution.util.TaxonList;
+import dr.evomodel.tree.BranchLengthStatistic;
+import dr.evomodel.tree.TMRCAStatistic;
+import dr.inference.model.Statistic;
+import dr.xml.*;
+
+/**
+ *
+ * To get the length of a stem branch of an MRCA:
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ * @author Alexei Drummond
+ * @author Andrew Rambaut
+ */
+public class BranchLengthStatisticParser extends AbstractXMLObjectParser {
+
+ public static final String BRANCH_LENGTH_STATISTIC = "branchLengthStatistic";
+ public static final String MRCA = "mrca";
+
+ public String getParserName() {
+ return BRANCH_LENGTH_STATISTIC;
+ }
+
+ public Object parseXMLObject(XMLObject xo) throws XMLParseException {
+
+ String name = xo.getAttribute(Statistic.NAME, xo.getId());
+ Tree tree = (Tree) xo.getChild(Tree.class);
+ TaxonList taxa = null;
+
+ if (xo.hasChildNamed(MRCA)) {
+ taxa = (TaxonList) xo.getElementFirstChild(MRCA);
+ }
+
+ try {
+ return new BranchLengthStatistic(name, tree, taxa);
+ } catch (TreeUtils.MissingTaxonException mte) {
+ throw new XMLParseException(
+ "Taxon, " + mte + ", in " + getParserName() + "was not found in the tree.");
+ }
+ }
+
+ //************************************************************************
+ // AbstractXMLObjectParser implementation
+ //************************************************************************
+
+ public String getParserDescription() {
+ return "A statistic that has as its value the height of the most recent common ancestor " +
+ "of a set of taxa in a given tree. ";
+ }
+
+ public Class getReturnType() {
+ return BranchLengthStatistic.class;
+ }
+
+ public XMLSyntaxRule[] getSyntaxRules() {
+ return rules;
+ }
+
+ private final XMLSyntaxRule[] rules = {
+ new ElementRule(Tree.class),
+ new StringAttributeRule("name",
+ "A name for this statistic primarily for the purposes of logging", true),
+ new ElementRule(MRCA,
+ new XMLSyntaxRule[]{new ElementRule(Taxa.class)}, true)
+ };
+
+}
diff --git a/src/dr/evomodelxml/tree/TreeModelParser.java b/src/dr/evomodelxml/tree/TreeModelParser.java
index 8ede318402..d35a3048df 100644
--- a/src/dr/evomodelxml/tree/TreeModelParser.java
+++ b/src/dr/evomodelxml/tree/TreeModelParser.java
@@ -263,10 +263,28 @@ public Object parseXMLObject(XMLObject xo) throws XMLParseException {
throw new XMLParseException("illegal child element in " + getParserName() + ": " + xo.getChildName(i) + " " + xo.getChild(i));
}
}
-
+
+ double minTaxonHeight = Double.MAX_VALUE;
+ double maxTaxonHeight = -Double.MAX_VALUE;
+ for (int i = 0; i < treeModel.getTaxonCount(); i++) {
+ Taxon taxon = treeModel.getTaxon(i);
+ double h = 0;
+ if (taxon.getDate() != null) {
+ h = Taxon.getHeightFromDate(taxon.getDate());
+ }
+ if (h < minTaxonHeight) {
+ minTaxonHeight = h;
+ }
+ if (h > maxTaxonHeight) {
+ maxTaxonHeight = h;
+ }
+ }
+
// Logger.getLogger("dr.evomodel").info(" initial tree topology = " + TreeUtils.uniqueNewick(treeModel, treeModel.getRoot()));
- Logger.getLogger("dr.evomodel").info(" taxon count = " + treeModel.getExternalNodeCount());
- Logger.getLogger("dr.evomodel").info(" tree height = " + treeModel.getNodeHeight(treeModel.getRoot()));
+ Logger.getLogger("dr.evomodel").info(" taxon count = " + treeModel.getExternalNodeCount());
+ Logger.getLogger("dr.evomodel").info(" tree height = " + treeModel.getNodeHeight(treeModel.getRoot()));
+ Logger.getLogger("dr.evomodel").info(" min tip height = " + minTaxonHeight);
+ Logger.getLogger("dr.evomodel").info(" max tip height = " + maxTaxonHeight);
return treeModel;
}
diff --git a/src/dr/evomodelxml/treedatalikelihood/TreeDataLikelihoodParser.java b/src/dr/evomodelxml/treedatalikelihood/TreeDataLikelihoodParser.java
index 39b14e4eb3..9c70992e73 100644
--- a/src/dr/evomodelxml/treedatalikelihood/TreeDataLikelihoodParser.java
+++ b/src/dr/evomodelxml/treedatalikelihood/TreeDataLikelihoodParser.java
@@ -50,6 +50,7 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.logging.Logger;
/**
* @author Andrew Rambaut
@@ -91,6 +92,9 @@ protected Likelihood createTreeDataLikelihood(List patternLists,
boolean delayRescalingUntilUnderflow,
PreOrderSettings settings) throws XMLParseException {
+ final Logger logger = Logger.getLogger("dr.evomodel");
+ logger.info("\nCreating tree data likelihoods for " + patternLists.size() + " partitions");
+
if (tipStatesModel != null) {
throw new XMLParseException("Tip State Error models are not supported yet with TreeDataLikelihood");
}
@@ -267,16 +271,16 @@ public Object parseXMLObject(XMLObject xo) throws XMLParseException {
patternList = (PatternList) cxo.getChild(PatternList.class);
patternLists.add(patternList);
- GammaSiteRateModel siteRateModel = (GammaSiteRateModel) cxo.getChild(GammaSiteRateModel.class);
+ SiteRateModel siteRateModel = (SiteRateModel) cxo.getChild(SiteRateModel.class);
siteRateModels.add(siteRateModel);
FrequencyModel rootFreqModel = (FrequencyModel) xo.getChild(FrequencyModel.class);
BranchModel branchModel = (BranchModel) cxo.getChild(BranchModel.class);
if (branchModel == null) {
- SubstitutionModel substitutionModel = (SubstitutionModel) xo.getChild(SubstitutionModel.class);
- if (substitutionModel == null) {
- substitutionModel = siteRateModel.getSubstitutionModel();
+ SubstitutionModel substitutionModel = (SubstitutionModel) cxo.getChild(SubstitutionModel.class);
+ if (substitutionModel == null && siteRateModel instanceof GammaSiteRateModel) {
+ substitutionModel = ((GammaSiteRateModel)siteRateModel).getSubstitutionModel();
}
if (substitutionModel == null) {
throw new XMLParseException("No substitution model available for partition " + k + " in DataTreeLikelihood: "+xo.getId());
diff --git a/src/dr/evoxml/SitePatternsParser.java b/src/dr/evoxml/SitePatternsParser.java
index f552a25942..afe58bf9d0 100644
--- a/src/dr/evoxml/SitePatternsParser.java
+++ b/src/dr/evoxml/SitePatternsParser.java
@@ -117,7 +117,7 @@ public Object parseXMLObject(XMLObject xo) throws XMLParseException {
if (xo.hasAttribute(XMLParser.ID)) {
final Logger logger = Logger.getLogger("dr.evoxml");
- logger.info("Site patterns '" + xo.getId() + "' created from positions " +
+ logger.info("\nSite patterns '" + xo.getId() + "' created from positions " +
Integer.toString(f) + "-" + Integer.toString(t) +
" of alignment '" + alignment.getId() + "'");
diff --git a/src/dr/evoxml/TaxaParser.java b/src/dr/evoxml/TaxaParser.java
index 4c77315c0b..5259ed8b41 100644
--- a/src/dr/evoxml/TaxaParser.java
+++ b/src/dr/evoxml/TaxaParser.java
@@ -30,6 +30,8 @@
import dr.evolution.util.TaxonList;
import dr.xml.*;
+import java.util.logging.Logger;
+
/**
* @author Alexei Drummond
* @author Andrew Rambaut
@@ -81,6 +83,10 @@ public Object parseXMLObject(XMLObject xo) throws XMLParseException {
}
}
+ final Logger logger = Logger.getLogger("dr.evoxml");
+ logger.info("\nTaxon list '" + xo.getId() + "' created with " + taxonList.getTaxonCount() + " taxa.");
+ logger.info(" most recent taxon date = " + Taxon.getMostRecentDate());
+
return taxonList;
}
diff --git a/src/dr/inference/loggers/TimeLogger.java b/src/dr/inference/loggers/TimeLogger.java
new file mode 100644
index 0000000000..0eaa3dc70f
--- /dev/null
+++ b/src/dr/inference/loggers/TimeLogger.java
@@ -0,0 +1,32 @@
+package dr.inference.loggers;
+
+import dr.util.Timer;
+
+public class TimeLogger implements Loggable {
+
+ private final Timer timer;
+ private Boolean hasStarted = false;
+
+ public TimeLogger() {
+ this.timer = new Timer();
+ }
+
+
+ @Override
+ public LogColumn[] getColumns() {
+ return new LogColumn[]{
+ new LogColumn.Abstract("secondsElapsed") {
+
+ @Override
+ protected String getFormattedValue() {
+ if (!hasStarted) {
+ hasStarted = true;
+ timer.start();
+ }
+
+ return Double.toString(timer.toSeconds());
+ }
+ }
+ };
+ }
+}
diff --git a/src/dr/inference/model/SumParameter.java b/src/dr/inference/model/SumParameter.java
index 1c39ec349a..62621da89b 100644
--- a/src/dr/inference/model/SumParameter.java
+++ b/src/dr/inference/model/SumParameter.java
@@ -25,6 +25,7 @@
package dr.inference.model;
+import java.util.ArrayList;
import java.util.List;
/**
@@ -32,11 +33,14 @@
*/
public class SumParameter extends Parameter.Abstract implements VariableListener {
- public SumParameter(List parameterList) {
- this.parameterList = parameterList;
- dimension = parameterList.size() == 1 ? 1 : parameterList.get(0).getDimension();;
- for (Parameter p : parameterList) {
- p.addVariableListener(this);
+ public SumParameter(List statisticList) {
+ this.statisticList = statisticList;
+ dimension = statisticList.size() == 1 ? 1 : statisticList.get(0).getDimension();
+ for (Statistic s : statisticList) {
+ if (s instanceof Parameter) {
+ parameterList.add(((Parameter) s));
+ ((Parameter) s).addVariableListener(this);
+ }
}
}
@@ -73,15 +77,15 @@ protected void adoptValues(Parameter source) {
public double getParameterValue(int dim) {
double value = 0;
- if (dimension == 1) {
- value = parameterList.get(0).getParameterValue(0);
- for (int i = 1; i < parameterList.get(0).getDimension(); i++) {
- value += parameterList.get(0).getParameterValue(i);
+ if (statisticList.size() == 1) {
+ value = statisticList.get(0).getStatisticValue(0);
+ for (int i = 1; i < statisticList.get(0).getDimension(); i++) {
+ value += statisticList.get(0).getStatisticValue(i);
}
} else {
- value = parameterList.get(0).getParameterValue(dim);
- for (int i = 1; i < parameterList.size(); i++) {
- value += parameterList.get(i).getParameterValue(dim);
+ value = statisticList.get(0).getStatisticValue(dim);
+ for (int i = 1; i < statisticList.size(); i++) {
+ value += statisticList.get(i).getStatisticValue(dim);
}
}
return value;
@@ -102,8 +106,8 @@ public void setParameterValueNotifyChangedAll(int dim, double value){
public String getParameterName() {
if (getId() == null) {
StringBuilder sb = new StringBuilder("sum");
- for (Parameter p : parameterList) {
- sb.append(".").append(p.getId());
+ for (Statistic s : statisticList) {
+ sb.append(".").append(s.getId());
}
setId(sb.toString());
}
@@ -134,7 +138,8 @@ public void variableChangedEvent(Variable variable, int index, ChangeType type)
fireParameterChangedEvent(index,type);
}
- private final List parameterList;
+ private final List statisticList;
+ private final List parameterList = new ArrayList<>();
private final int dimension;
private Bounds bounds = null;
}
diff --git a/src/dr/inference/trace/LogFileTraces.java b/src/dr/inference/trace/LogFileTraces.java
index 90e480e120..a7f3c5409e 100644
--- a/src/dr/inference/trace/LogFileTraces.java
+++ b/src/dr/inference/trace/LogFileTraces.java
@@ -40,7 +40,8 @@
public class LogFileTraces extends AbstractTraceList {
public LogFileTraces(String name, File file) {
- this.name = name;
+ // trim off the extension if present.
+ this.name = name.toUpperCase().endsWith(".LOG") ? name.substring(0, name.length() - 4) : name;
this.file = file;
System.out.println("Loading log " + file.getAbsolutePath() + " ...");
}
@@ -52,6 +53,13 @@ public String getName() {
return name;
}
+ /**
+ * @return the path of this traceset
+ */
+ public String getFileName() {
+ return file.getName();
+ }
+
/**
* @return the path of this traceset
*/
diff --git a/src/dr/inferencexml/distribution/PriorParsers.java b/src/dr/inferencexml/distribution/PriorParsers.java
index b126df5146..6867227d7d 100644
--- a/src/dr/inferencexml/distribution/PriorParsers.java
+++ b/src/dr/inferencexml/distribution/PriorParsers.java
@@ -79,6 +79,7 @@ public class PriorParsers {
public static final String HALF_T_PRIOR = "halfTPrior";
public static final String DIRICHLET_PRIOR = "dirichletPrior";
public static final String ALPHA = "alpha";
+ public static final String BETA = "beta";
public static final String COUNTS = "counts";
public static final String SUMS_TO = "sumsTo";
@@ -849,8 +850,15 @@ public String getParserName() {
public Object parseXMLObject(XMLObject xo) throws XMLParseException {
- final double shape = xo.getDoubleAttribute(SHAPE);
- final double shapeB = xo.getDoubleAttribute(SHAPEB);
+ double shape;
+ double shapeB;
+ if (xo.hasAttribute(ALPHA) && xo.hasAttribute(BETA)) {
+ shape = xo.getDoubleAttribute(ALPHA);
+ shapeB = xo.getDoubleAttribute(BETA);
+ } else {
+ shape = xo.getDoubleAttribute(SHAPE);
+ shapeB = xo.getDoubleAttribute(SHAPEB);
+ }
final double offset = xo.getAttribute(OFFSET, 0.0);
final double scale = xo.getAttribute(SCALE, 1.0);
@@ -871,8 +879,16 @@ public XMLSyntaxRule[] getSyntaxRules() {
}
private final XMLSyntaxRule[] rules = {
- AttributeRule.newDoubleRule(SHAPE),
- AttributeRule.newDoubleRule(SHAPEB),
+ new XORRule(
+ new AndRule(
+ AttributeRule.newDoubleRule(SHAPE),
+ AttributeRule.newDoubleRule(SHAPEB)
+ ),
+ new AndRule(
+ AttributeRule.newDoubleRule(ALPHA),
+ AttributeRule.newDoubleRule(BETA)
+ )
+ ),
AttributeRule.newDoubleRule(OFFSET, true),
new ElementRule(Statistic.class, 1, Integer.MAX_VALUE)
};
diff --git a/src/dr/inferencexml/hmc/CompoundGradientParser.java b/src/dr/inferencexml/hmc/CompoundGradientParser.java
index 44fffcd99c..6bb1d63466 100644
--- a/src/dr/inferencexml/hmc/CompoundGradientParser.java
+++ b/src/dr/inferencexml/hmc/CompoundGradientParser.java
@@ -28,7 +28,6 @@
import dr.inference.distribution.DistributionLikelihood;
import dr.inference.distribution.MultivariateDistributionLikelihood;
import dr.inference.hmc.CompoundDerivative;
-import dr.inference.hmc.CompoundGradient;
import dr.inference.hmc.GradientWrtParameterProvider;
import dr.inference.model.*;
import dr.xml.*;
@@ -57,15 +56,13 @@ public String[] getParserNames() {
@Override
public Object parseXMLObject(XMLObject xo) throws XMLParseException {
- List gradList = new ArrayList();
- List likelihoodList = new ArrayList(); // TODO Remove?
+ List gradList = new ArrayList<>();
for (int i = 0; i < xo.getChildCount(); ++i) {
Object obj = xo.getChild(i);
GradientWrtParameterProvider grad;
- Likelihood likelihood;
if (obj instanceof DistributionLikelihood) {
DistributionLikelihood dl = (DistributionLikelihood) obj;
@@ -83,19 +80,16 @@ public Object parseXMLObject(XMLObject xo) throws XMLParseException {
final GradientProvider provider = (GradientProvider) mdl.getDistribution();
final Parameter parameter = mdl.getDataParameter();
- likelihood = mdl;
grad = new GradientWrtParameterProvider.ParameterWrapper(provider, parameter, mdl);
} else if (obj instanceof GradientWrtParameterProvider) {
grad = (GradientWrtParameterProvider) obj;
- likelihood = grad.getLikelihood();
} else {
throw new XMLParseException("Not a Gaussian process");
}
gradList.add(grad);
- likelihoodList.add(likelihood);
}
return new CompoundDerivative(gradList);
diff --git a/src/dr/inferencexml/hmc/JointGradientParser.java b/src/dr/inferencexml/hmc/JointGradientParser.java
index e34890fbcb..ccad9b2f1d 100644
--- a/src/dr/inferencexml/hmc/JointGradientParser.java
+++ b/src/dr/inferencexml/hmc/JointGradientParser.java
@@ -40,7 +40,7 @@
public class JointGradientParser extends AbstractXMLObjectParser {
private final static String SUM_DERIVATIVE = "sumDerivative";
- private final static String SUM_DERIVATIVE2 = "jointGradient";
+ public final static String SUM_DERIVATIVE2 = "jointGradient";
private static final String THREADS = "threads";
@Override
diff --git a/src/dr/inferencexml/loggers/TimeLoggerXMLParser.java b/src/dr/inferencexml/loggers/TimeLoggerXMLParser.java
new file mode 100644
index 0000000000..43ca1d5564
--- /dev/null
+++ b/src/dr/inferencexml/loggers/TimeLoggerXMLParser.java
@@ -0,0 +1,34 @@
+package dr.inferencexml.loggers;
+
+import dr.inference.loggers.TimeLogger;
+import dr.xml.AbstractXMLObjectParser;
+import dr.xml.XMLObject;
+import dr.xml.XMLParseException;
+import dr.xml.XMLSyntaxRule;
+
+public class TimeLoggerXMLParser extends AbstractXMLObjectParser {
+ @Override
+ public Object parseXMLObject(XMLObject xo) throws XMLParseException {
+ return new TimeLogger();
+ }
+
+ @Override
+ public XMLSyntaxRule[] getSyntaxRules() {
+ return new XMLSyntaxRule[0];
+ }
+
+ @Override
+ public String getParserDescription() {
+ return "saves elapsed seconds to log file";
+ }
+
+ @Override
+ public Class getReturnType() {
+ return TimeLogger.class;
+ }
+
+ @Override
+ public String getParserName() {
+ return "timeLogger";
+ }
+}
diff --git a/src/dr/inferencexml/model/SumParameterParser.java b/src/dr/inferencexml/model/SumParameterParser.java
index ee10d75146..7a9ea283e1 100644
--- a/src/dr/inferencexml/model/SumParameterParser.java
+++ b/src/dr/inferencexml/model/SumParameterParser.java
@@ -25,6 +25,7 @@
package dr.inferencexml.model;
+import dr.inference.model.Statistic;
import dr.inference.model.SumParameter;
import dr.inference.model.Parameter;
import dr.xml.*;
@@ -41,30 +42,33 @@ public class SumParameterParser extends AbstractXMLObjectParser {
public Object parseXMLObject(XMLObject xo) throws XMLParseException {
- List paramList = new ArrayList();
+ List statisticList = new ArrayList<>();
int dim = -1;
for (int i = 0; i < xo.getChildCount(); ++i) {
- Parameter parameter = (Parameter) xo.getChild(i);
+ Statistic s = (Statistic) xo.getChild(i);
if (dim == -1) {
- dim = parameter.getDimension();
+ dim = s.getDimension();
} else {
- if (parameter.getDimension() != dim) {
- throw new XMLParseException("All parameters in sum '" + xo.getId() + "' must be the same length");
+ if (s.getDimension() != dim) {
+ throw new XMLParseException("All statistics/parameters in sum '" + xo.getId() + "' must be the same length");
}
}
- paramList.add(parameter);
+ statisticList.add(s);
}
- boolean sumAll = xo.getBooleanAttribute(SUM_ALL);
+ boolean sumAll = statisticList.size() == 1;
+ if (xo.hasAttribute(SUM_ALL)) {
+ sumAll = xo.getBooleanAttribute(SUM_ALL);
+ }
- if (sumAll && paramList.size() > 1) {
+ if (sumAll && statisticList.size() > 1) {
throw new XMLParseException("To sum all the elements, only one parameter should be given");
}
- if (!sumAll && paramList.size() < 2) {
+ if (!sumAll && statisticList.size() < 2) {
throw new XMLParseException("For an element-wise sum, more than one parameter should be given");
}
- return new SumParameter(paramList);
+ return new SumParameter(statisticList);
}
public XMLSyntaxRule[] getSyntaxRules() {
@@ -72,11 +76,11 @@ public XMLSyntaxRule[] getSyntaxRules() {
}
private final XMLSyntaxRule[] rules = {
- new ElementRule(Parameter.class,1,Integer.MAX_VALUE),
+ new ElementRule(Statistic.class,1,Integer.MAX_VALUE),
};
public String getParserDescription() {
- return "A element-wise sum of parameters.";
+ return "A element-wise sum of statistics or parameters.";
}
public Class getReturnType() {
diff --git a/src/dr/inferencexml/operators/hmc/HamiltonianMonteCarloOperatorParser.java b/src/dr/inferencexml/operators/hmc/HamiltonianMonteCarloOperatorParser.java
index 5baf66f2ae..262c573ffe 100644
--- a/src/dr/inferencexml/operators/hmc/HamiltonianMonteCarloOperatorParser.java
+++ b/src/dr/inferencexml/operators/hmc/HamiltonianMonteCarloOperatorParser.java
@@ -44,19 +44,22 @@
public class HamiltonianMonteCarloOperatorParser extends AbstractXMLObjectParser {
- private final static String HMC_OPERATOR = "hamiltonianMonteCarloOperator";
- private final static String N_STEPS = "nSteps";
- private final static String STEP_SIZE = "stepSize";
+ public final static String HMC_OPERATOR = "hamiltonianMonteCarloOperator";
+ public final static String N_STEPS = "nSteps";
+ public final static String STEP_SIZE = "stepSize";
private final static String RANDOM_STEP_FRACTION = "randomStepCountFraction";
- private final static String PRECONDITIONING = "preconditioning";
+ public final static String PRECONDITIONING = "preconditioning";
private final static String PRECONDITIONER = "preconditioner";
- private final static String GRADIENT_CHECK_COUNT = "gradientCheckCount";
+ public final static String GRADIENT_CHECK_COUNT = "gradientCheckCount";
public final static String GRADIENT_CHECK_TOLERANCE = "gradientCheckTolerance";
private final static String MAX_ITERATIONS = "checkStepSizeMaxIterations";
private final static String REDUCTION_FACTOR = "checkStepSizeReductionFactor";
private final static String TARGET_ACCEPTANCE_PROBABILITY = "targetAcceptanceProbability";
private final static String INSTABILITY_HANDLER = "instabilityHandler";
private final static String MASK = "mask";
+ //these are in the Skygrid+HMC XML files but were not (yet) defined here
+ public final static String MODE = "mode";
+ public final static String PRECONDITIONING_UPDATE_FREQUENCY = "preconditioningUpdateFrequency";
@Override
public String getParserName() {
diff --git a/src/dr/math/GeneralisedGaussLaguerreQuadrature.java b/src/dr/math/GeneralisedGaussLaguerreQuadrature.java
index 9cbfc830da..05f4a60e27 100644
--- a/src/dr/math/GeneralisedGaussLaguerreQuadrature.java
+++ b/src/dr/math/GeneralisedGaussLaguerreQuadrature.java
@@ -168,5 +168,12 @@ public double logIntegrate(UnivariateFunction f, double min){
}
+ public double[] getAbscissae() {
+ return abscissae;
+ }
+
+ public double[] getCoefficients() {
+ return coefficients;
+ }
}