PHYLIPNEW-3.69.650/ 0002775 0001750 0001750 00000000000 12171071713 010350 5 0000000 0000000 PHYLIPNEW-3.69.650/config.sub 0000755 0001750 0001750 00000105327 12171071677 012270 0000000 0000000 #! /bin/sh
# Configuration validation subroutine script.
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
# 2011, 2012 Free Software Foundation, Inc.
timestamp='2012-04-18'
# This file is (in principle) common to ALL GNU software.
# The presence of a machine in this file suggests that SOME GNU software
# can handle that machine. It does not imply ALL GNU software can.
#
# This file is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, see .
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# Please send patches to . Submit a context
# diff and a properly formatted GNU ChangeLog entry.
#
# Configuration subroutine to validate and canonicalize a configuration type.
# Supply the specified configuration type as an argument.
# If it is invalid, we print an error message on stderr and exit with code 1.
# Otherwise, we print the canonical config type on stdout and succeed.
# You can get the latest version of this script from:
# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
# This file is supposed to be the same for all GNU packages
# and recognize all the CPU types, system types and aliases
# that are meaningful with *any* GNU software.
# Each package is responsible for reporting which valid configurations
# it does not support. The user should be able to distinguish
# a failure to support a valid configuration from a meaningless
# configuration.
# The goal of this file is to map all the various variations of a given
# machine specification into a single specification in the form:
# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
# or in some cases, the newer four-part form:
# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
# It is wrong to echo any other type of specification.
me=`echo "$0" | sed -e 's,.*/,,'`
usage="\
Usage: $0 [OPTION] CPU-MFR-OPSYS
$0 [OPTION] ALIAS
Canonicalize a configuration name.
Operation modes:
-h, --help print this help, then exit
-t, --time-stamp print date of last modification, then exit
-v, --version print version number, then exit
Report bugs and patches to ."
version="\
GNU config.sub ($timestamp)
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
help="
Try \`$me --help' for more information."
# Parse command line
while test $# -gt 0 ; do
case $1 in
--time-stamp | --time* | -t )
echo "$timestamp" ; exit ;;
--version | -v )
echo "$version" ; exit ;;
--help | --h* | -h )
echo "$usage"; exit ;;
-- ) # Stop option processing
shift; break ;;
- ) # Use stdin as input.
break ;;
-* )
echo "$me: invalid option $1$help"
exit 1 ;;
*local*)
# First pass through any local machine types.
echo $1
exit ;;
* )
break ;;
esac
done
case $# in
0) echo "$me: missing argument$help" >&2
exit 1;;
1) ;;
*) echo "$me: too many arguments$help" >&2
exit 1;;
esac
# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
# Here we must recognize all the valid KERNEL-OS combinations.
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
case $maybe_os in
nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
knetbsd*-gnu* | netbsd*-gnu* | \
kopensolaris*-gnu* | \
storm-chaos* | os2-emx* | rtmk-nova*)
os=-$maybe_os
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
;;
android-linux)
os=-linux-android
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown
;;
*)
basic_machine=`echo $1 | sed 's/-[^-]*$//'`
if [ $basic_machine != $1 ]
then os=`echo $1 | sed 's/.*-/-/'`
else os=; fi
;;
esac
### Let's recognize common machines as not being operating systems so
### that things like config.sub decstation-3100 work. We also
### recognize some manufacturers as not being operating systems, so we
### can provide default operating systems below.
case $os in
-sun*os*)
# Prevent following clause from handling this invalid input.
;;
-dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
-att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
-unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
-apple | -axis | -knuth | -cray | -microblaze)
os=
basic_machine=$1
;;
-bluegene*)
os=-cnk
;;
-sim | -cisco | -oki | -wec | -winbond)
os=
basic_machine=$1
;;
-scout)
;;
-wrs)
os=-vxworks
basic_machine=$1
;;
-chorusos*)
os=-chorusos
basic_machine=$1
;;
-chorusrdb)
os=-chorusrdb
basic_machine=$1
;;
-hiux*)
os=-hiuxwe2
;;
-sco6)
os=-sco5v6
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-sco5)
os=-sco3.2v5
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-sco4)
os=-sco3.2v4
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-sco3.2.[4-9]*)
os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-sco3.2v[4-9]*)
# Don't forget version if it is 3.2v4 or newer.
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-sco5v6*)
# Don't forget version if it is 3.2v4 or newer.
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-sco*)
os=-sco3.2v2
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-udk*)
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-isc)
os=-isc2.2
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-clix*)
basic_machine=clipper-intergraph
;;
-isc*)
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-lynx*178)
os=-lynxos178
;;
-lynx*5)
os=-lynxos5
;;
-lynx*)
os=-lynxos
;;
-ptx*)
basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
;;
-windowsnt*)
os=`echo $os | sed -e 's/windowsnt/winnt/'`
;;
-psos*)
os=-psos
;;
-mint | -mint[0-9]*)
basic_machine=m68k-atari
os=-mint
;;
esac
# Decode aliases for certain CPU-COMPANY combinations.
case $basic_machine in
# Recognize the basic CPU types without company name.
# Some are omitted here because they have special meanings below.
1750a | 580 \
| a29k \
| aarch64 | aarch64_be \
| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
| am33_2.0 \
| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
| be32 | be64 \
| bfin \
| c4x | clipper \
| d10v | d30v | dlx | dsp16xx \
| epiphany \
| fido | fr30 | frv \
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
| hexagon \
| i370 | i860 | i960 | ia64 \
| ip2k | iq2000 \
| le32 | le64 \
| lm32 \
| m32c | m32r | m32rle | m68000 | m68k | m88k \
| maxq | mb | microblaze | mcore | mep | metag \
| mips | mipsbe | mipseb | mipsel | mipsle \
| mips16 \
| mips64 | mips64el \
| mips64octeon | mips64octeonel \
| mips64orion | mips64orionel \
| mips64r5900 | mips64r5900el \
| mips64vr | mips64vrel \
| mips64vr4100 | mips64vr4100el \
| mips64vr4300 | mips64vr4300el \
| mips64vr5000 | mips64vr5000el \
| mips64vr5900 | mips64vr5900el \
| mipsisa32 | mipsisa32el \
| mipsisa32r2 | mipsisa32r2el \
| mipsisa64 | mipsisa64el \
| mipsisa64r2 | mipsisa64r2el \
| mipsisa64sb1 | mipsisa64sb1el \
| mipsisa64sr71k | mipsisa64sr71kel \
| mipstx39 | mipstx39el \
| mn10200 | mn10300 \
| moxie \
| mt \
| msp430 \
| nds32 | nds32le | nds32be \
| nios | nios2 \
| ns16k | ns32k \
| open8 \
| or32 \
| pdp10 | pdp11 | pj | pjl \
| powerpc | powerpc64 | powerpc64le | powerpcle \
| pyramid \
| rl78 | rx \
| score \
| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
| sh64 | sh64le \
| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
| spu \
| tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
| ubicom32 \
| v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
| we32k \
| x86 | xc16x | xstormy16 | xtensa \
| z8k | z80)
basic_machine=$basic_machine-unknown
;;
c54x)
basic_machine=tic54x-unknown
;;
c55x)
basic_machine=tic55x-unknown
;;
c6x)
basic_machine=tic6x-unknown
;;
m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip)
basic_machine=$basic_machine-unknown
os=-none
;;
m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
;;
ms1)
basic_machine=mt-unknown
;;
strongarm | thumb | xscale)
basic_machine=arm-unknown
;;
xgate)
basic_machine=$basic_machine-unknown
os=-none
;;
xscaleeb)
basic_machine=armeb-unknown
;;
xscaleel)
basic_machine=armel-unknown
;;
# We use `pc' rather than `unknown'
# because (1) that's what they normally are, and
# (2) the word "unknown" tends to confuse beginning users.
i*86 | x86_64)
basic_machine=$basic_machine-pc
;;
# Object if more than one company name word.
*-*-*)
echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
exit 1
;;
# Recognize the basic CPU types with company name.
580-* \
| a29k-* \
| aarch64-* | aarch64_be-* \
| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
| arm-* | armbe-* | armle-* | armeb-* | armv*-* \
| avr-* | avr32-* \
| be32-* | be64-* \
| bfin-* | bs2000-* \
| c[123]* | c30-* | [cjt]90-* | c4x-* \
| clipper-* | craynv-* | cydra-* \
| d10v-* | d30v-* | dlx-* \
| elxsi-* \
| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
| h8300-* | h8500-* \
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
| hexagon-* \
| i*86-* | i860-* | i960-* | ia64-* \
| ip2k-* | iq2000-* \
| le32-* | le64-* \
| lm32-* \
| m32c-* | m32r-* | m32rle-* \
| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
| m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \
| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
| mips16-* \
| mips64-* | mips64el-* \
| mips64octeon-* | mips64octeonel-* \
| mips64orion-* | mips64orionel-* \
| mips64r5900-* | mips64r5900el-* \
| mips64vr-* | mips64vrel-* \
| mips64vr4100-* | mips64vr4100el-* \
| mips64vr4300-* | mips64vr4300el-* \
| mips64vr5000-* | mips64vr5000el-* \
| mips64vr5900-* | mips64vr5900el-* \
| mipsisa32-* | mipsisa32el-* \
| mipsisa32r2-* | mipsisa32r2el-* \
| mipsisa64-* | mipsisa64el-* \
| mipsisa64r2-* | mipsisa64r2el-* \
| mipsisa64sb1-* | mipsisa64sb1el-* \
| mipsisa64sr71k-* | mipsisa64sr71kel-* \
| mipstx39-* | mipstx39el-* \
| mmix-* \
| mt-* \
| msp430-* \
| nds32-* | nds32le-* | nds32be-* \
| nios-* | nios2-* \
| none-* | np1-* | ns16k-* | ns32k-* \
| open8-* \
| orion-* \
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
| pyramid-* \
| rl78-* | romp-* | rs6000-* | rx-* \
| sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
| sparclite-* \
| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \
| tahoe-* \
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
| tile*-* \
| tron-* \
| ubicom32-* \
| v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
| vax-* \
| we32k-* \
| x86-* | x86_64-* | xc16x-* | xps100-* \
| xstormy16-* | xtensa*-* \
| ymp-* \
| z8k-* | z80-*)
;;
# Recognize the basic CPU types without company name, with glob match.
xtensa*)
basic_machine=$basic_machine-unknown
;;
# Recognize the various machine names and aliases which stand
# for a CPU type and a company and sometimes even an OS.
386bsd)
basic_machine=i386-unknown
os=-bsd
;;
3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
basic_machine=m68000-att
;;
3b*)
basic_machine=we32k-att
;;
a29khif)
basic_machine=a29k-amd
os=-udi
;;
abacus)
basic_machine=abacus-unknown
;;
adobe68k)
basic_machine=m68010-adobe
os=-scout
;;
alliant | fx80)
basic_machine=fx80-alliant
;;
altos | altos3068)
basic_machine=m68k-altos
;;
am29k)
basic_machine=a29k-none
os=-bsd
;;
amd64)
basic_machine=x86_64-pc
;;
amd64-*)
basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
amdahl)
basic_machine=580-amdahl
os=-sysv
;;
amiga | amiga-*)
basic_machine=m68k-unknown
;;
amigaos | amigados)
basic_machine=m68k-unknown
os=-amigaos
;;
amigaunix | amix)
basic_machine=m68k-unknown
os=-sysv4
;;
apollo68)
basic_machine=m68k-apollo
os=-sysv
;;
apollo68bsd)
basic_machine=m68k-apollo
os=-bsd
;;
aros)
basic_machine=i386-pc
os=-aros
;;
aux)
basic_machine=m68k-apple
os=-aux
;;
balance)
basic_machine=ns32k-sequent
os=-dynix
;;
blackfin)
basic_machine=bfin-unknown
os=-linux
;;
blackfin-*)
basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
os=-linux
;;
bluegene*)
basic_machine=powerpc-ibm
os=-cnk
;;
c54x-*)
basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
c55x-*)
basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
c6x-*)
basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
c90)
basic_machine=c90-cray
os=-unicos
;;
cegcc)
basic_machine=arm-unknown
os=-cegcc
;;
convex-c1)
basic_machine=c1-convex
os=-bsd
;;
convex-c2)
basic_machine=c2-convex
os=-bsd
;;
convex-c32)
basic_machine=c32-convex
os=-bsd
;;
convex-c34)
basic_machine=c34-convex
os=-bsd
;;
convex-c38)
basic_machine=c38-convex
os=-bsd
;;
cray | j90)
basic_machine=j90-cray
os=-unicos
;;
craynv)
basic_machine=craynv-cray
os=-unicosmp
;;
cr16 | cr16-*)
basic_machine=cr16-unknown
os=-elf
;;
crds | unos)
basic_machine=m68k-crds
;;
crisv32 | crisv32-* | etraxfs*)
basic_machine=crisv32-axis
;;
cris | cris-* | etrax*)
basic_machine=cris-axis
;;
crx)
basic_machine=crx-unknown
os=-elf
;;
da30 | da30-*)
basic_machine=m68k-da30
;;
decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
basic_machine=mips-dec
;;
decsystem10* | dec10*)
basic_machine=pdp10-dec
os=-tops10
;;
decsystem20* | dec20*)
basic_machine=pdp10-dec
os=-tops20
;;
delta | 3300 | motorola-3300 | motorola-delta \
| 3300-motorola | delta-motorola)
basic_machine=m68k-motorola
;;
delta88)
basic_machine=m88k-motorola
os=-sysv3
;;
dicos)
basic_machine=i686-pc
os=-dicos
;;
djgpp)
basic_machine=i586-pc
os=-msdosdjgpp
;;
dpx20 | dpx20-*)
basic_machine=rs6000-bull
os=-bosx
;;
dpx2* | dpx2*-bull)
basic_machine=m68k-bull
os=-sysv3
;;
ebmon29k)
basic_machine=a29k-amd
os=-ebmon
;;
elxsi)
basic_machine=elxsi-elxsi
os=-bsd
;;
encore | umax | mmax)
basic_machine=ns32k-encore
;;
es1800 | OSE68k | ose68k | ose | OSE)
basic_machine=m68k-ericsson
os=-ose
;;
fx2800)
basic_machine=i860-alliant
;;
genix)
basic_machine=ns32k-ns
;;
gmicro)
basic_machine=tron-gmicro
os=-sysv
;;
go32)
basic_machine=i386-pc
os=-go32
;;
h3050r* | hiux*)
basic_machine=hppa1.1-hitachi
os=-hiuxwe2
;;
h8300hms)
basic_machine=h8300-hitachi
os=-hms
;;
h8300xray)
basic_machine=h8300-hitachi
os=-xray
;;
h8500hms)
basic_machine=h8500-hitachi
os=-hms
;;
harris)
basic_machine=m88k-harris
os=-sysv3
;;
hp300-*)
basic_machine=m68k-hp
;;
hp300bsd)
basic_machine=m68k-hp
os=-bsd
;;
hp300hpux)
basic_machine=m68k-hp
os=-hpux
;;
hp3k9[0-9][0-9] | hp9[0-9][0-9])
basic_machine=hppa1.0-hp
;;
hp9k2[0-9][0-9] | hp9k31[0-9])
basic_machine=m68000-hp
;;
hp9k3[2-9][0-9])
basic_machine=m68k-hp
;;
hp9k6[0-9][0-9] | hp6[0-9][0-9])
basic_machine=hppa1.0-hp
;;
hp9k7[0-79][0-9] | hp7[0-79][0-9])
basic_machine=hppa1.1-hp
;;
hp9k78[0-9] | hp78[0-9])
# FIXME: really hppa2.0-hp
basic_machine=hppa1.1-hp
;;
hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
# FIXME: really hppa2.0-hp
basic_machine=hppa1.1-hp
;;
hp9k8[0-9][13679] | hp8[0-9][13679])
basic_machine=hppa1.1-hp
;;
hp9k8[0-9][0-9] | hp8[0-9][0-9])
basic_machine=hppa1.0-hp
;;
hppa-next)
os=-nextstep3
;;
hppaosf)
basic_machine=hppa1.1-hp
os=-osf
;;
hppro)
basic_machine=hppa1.1-hp
os=-proelf
;;
i370-ibm* | ibm*)
basic_machine=i370-ibm
;;
i*86v32)
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
os=-sysv32
;;
i*86v4*)
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
os=-sysv4
;;
i*86v)
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
os=-sysv
;;
i*86sol2)
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
os=-solaris2
;;
i386mach)
basic_machine=i386-mach
os=-mach
;;
i386-vsta | vsta)
basic_machine=i386-unknown
os=-vsta
;;
iris | iris4d)
basic_machine=mips-sgi
case $os in
-irix*)
;;
*)
os=-irix4
;;
esac
;;
isi68 | isi)
basic_machine=m68k-isi
os=-sysv
;;
m68knommu)
basic_machine=m68k-unknown
os=-linux
;;
m68knommu-*)
basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
os=-linux
;;
m88k-omron*)
basic_machine=m88k-omron
;;
magnum | m3230)
basic_machine=mips-mips
os=-sysv
;;
merlin)
basic_machine=ns32k-utek
os=-sysv
;;
microblaze)
basic_machine=microblaze-xilinx
;;
mingw32)
basic_machine=i386-pc
os=-mingw32
;;
mingw32ce)
basic_machine=arm-unknown
os=-mingw32ce
;;
miniframe)
basic_machine=m68000-convergent
;;
*mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
basic_machine=m68k-atari
os=-mint
;;
mips3*-*)
basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
;;
mips3*)
basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
;;
monitor)
basic_machine=m68k-rom68k
os=-coff
;;
morphos)
basic_machine=powerpc-unknown
os=-morphos
;;
msdos)
basic_machine=i386-pc
os=-msdos
;;
ms1-*)
basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
;;
msys)
basic_machine=i386-pc
os=-msys
;;
mvs)
basic_machine=i370-ibm
os=-mvs
;;
nacl)
basic_machine=le32-unknown
os=-nacl
;;
ncr3000)
basic_machine=i486-ncr
os=-sysv4
;;
netbsd386)
basic_machine=i386-unknown
os=-netbsd
;;
netwinder)
basic_machine=armv4l-rebel
os=-linux
;;
news | news700 | news800 | news900)
basic_machine=m68k-sony
os=-newsos
;;
news1000)
basic_machine=m68030-sony
os=-newsos
;;
news-3600 | risc-news)
basic_machine=mips-sony
os=-newsos
;;
necv70)
basic_machine=v70-nec
os=-sysv
;;
next | m*-next )
basic_machine=m68k-next
case $os in
-nextstep* )
;;
-ns2*)
os=-nextstep2
;;
*)
os=-nextstep3
;;
esac
;;
nh3000)
basic_machine=m68k-harris
os=-cxux
;;
nh[45]000)
basic_machine=m88k-harris
os=-cxux
;;
nindy960)
basic_machine=i960-intel
os=-nindy
;;
mon960)
basic_machine=i960-intel
os=-mon960
;;
nonstopux)
basic_machine=mips-compaq
os=-nonstopux
;;
np1)
basic_machine=np1-gould
;;
neo-tandem)
basic_machine=neo-tandem
;;
nse-tandem)
basic_machine=nse-tandem
;;
nsr-tandem)
basic_machine=nsr-tandem
;;
op50n-* | op60c-*)
basic_machine=hppa1.1-oki
os=-proelf
;;
openrisc | openrisc-*)
basic_machine=or32-unknown
;;
os400)
basic_machine=powerpc-ibm
os=-os400
;;
OSE68000 | ose68000)
basic_machine=m68000-ericsson
os=-ose
;;
os68k)
basic_machine=m68k-none
os=-os68k
;;
pa-hitachi)
basic_machine=hppa1.1-hitachi
os=-hiuxwe2
;;
paragon)
basic_machine=i860-intel
os=-osf
;;
parisc)
basic_machine=hppa-unknown
os=-linux
;;
parisc-*)
basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`
os=-linux
;;
pbd)
basic_machine=sparc-tti
;;
pbb)
basic_machine=m68k-tti
;;
pc532 | pc532-*)
basic_machine=ns32k-pc532
;;
pc98)
basic_machine=i386-pc
;;
pc98-*)
basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
pentium | p5 | k5 | k6 | nexgen | viac3)
basic_machine=i586-pc
;;
pentiumpro | p6 | 6x86 | athlon | athlon_*)
basic_machine=i686-pc
;;
pentiumii | pentium2 | pentiumiii | pentium3)
basic_machine=i686-pc
;;
pentium4)
basic_machine=i786-pc
;;
pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
pentiumpro-* | p6-* | 6x86-* | athlon-*)
basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
pentium4-*)
basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
pn)
basic_machine=pn-gould
;;
power) basic_machine=power-ibm
;;
ppc | ppcbe) basic_machine=powerpc-unknown
;;
ppc-* | ppcbe-*)
basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
ppcle | powerpclittle | ppc-le | powerpc-little)
basic_machine=powerpcle-unknown
;;
ppcle-* | powerpclittle-*)
basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
ppc64) basic_machine=powerpc64-unknown
;;
ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
ppc64le | powerpc64little | ppc64-le | powerpc64-little)
basic_machine=powerpc64le-unknown
;;
ppc64le-* | powerpc64little-*)
basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
ps2)
basic_machine=i386-ibm
;;
pw32)
basic_machine=i586-unknown
os=-pw32
;;
rdos)
basic_machine=i386-pc
os=-rdos
;;
rom68k)
basic_machine=m68k-rom68k
os=-coff
;;
rm[46]00)
basic_machine=mips-siemens
;;
rtpc | rtpc-*)
basic_machine=romp-ibm
;;
s390 | s390-*)
basic_machine=s390-ibm
;;
s390x | s390x-*)
basic_machine=s390x-ibm
;;
sa29200)
basic_machine=a29k-amd
os=-udi
;;
sb1)
basic_machine=mipsisa64sb1-unknown
;;
sb1el)
basic_machine=mipsisa64sb1el-unknown
;;
sde)
basic_machine=mipsisa32-sde
os=-elf
;;
sei)
basic_machine=mips-sei
os=-seiux
;;
sequent)
basic_machine=i386-sequent
;;
sh)
basic_machine=sh-hitachi
os=-hms
;;
sh5el)
basic_machine=sh5le-unknown
;;
sh64)
basic_machine=sh64-unknown
;;
sparclite-wrs | simso-wrs)
basic_machine=sparclite-wrs
os=-vxworks
;;
sps7)
basic_machine=m68k-bull
os=-sysv2
;;
spur)
basic_machine=spur-unknown
;;
st2000)
basic_machine=m68k-tandem
;;
stratus)
basic_machine=i860-stratus
os=-sysv4
;;
strongarm-* | thumb-*)
basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
sun2)
basic_machine=m68000-sun
;;
sun2os3)
basic_machine=m68000-sun
os=-sunos3
;;
sun2os4)
basic_machine=m68000-sun
os=-sunos4
;;
sun3os3)
basic_machine=m68k-sun
os=-sunos3
;;
sun3os4)
basic_machine=m68k-sun
os=-sunos4
;;
sun4os3)
basic_machine=sparc-sun
os=-sunos3
;;
sun4os4)
basic_machine=sparc-sun
os=-sunos4
;;
sun4sol2)
basic_machine=sparc-sun
os=-solaris2
;;
sun3 | sun3-*)
basic_machine=m68k-sun
;;
sun4)
basic_machine=sparc-sun
;;
sun386 | sun386i | roadrunner)
basic_machine=i386-sun
;;
sv1)
basic_machine=sv1-cray
os=-unicos
;;
symmetry)
basic_machine=i386-sequent
os=-dynix
;;
t3e)
basic_machine=alphaev5-cray
os=-unicos
;;
t90)
basic_machine=t90-cray
os=-unicos
;;
tile*)
basic_machine=$basic_machine-unknown
os=-linux-gnu
;;
tx39)
basic_machine=mipstx39-unknown
;;
tx39el)
basic_machine=mipstx39el-unknown
;;
toad1)
basic_machine=pdp10-xkl
os=-tops20
;;
tower | tower-32)
basic_machine=m68k-ncr
;;
tpf)
basic_machine=s390x-ibm
os=-tpf
;;
udi29k)
basic_machine=a29k-amd
os=-udi
;;
ultra3)
basic_machine=a29k-nyu
os=-sym1
;;
v810 | necv810)
basic_machine=v810-nec
os=-none
;;
vaxv)
basic_machine=vax-dec
os=-sysv
;;
vms)
basic_machine=vax-dec
os=-vms
;;
vpp*|vx|vx-*)
basic_machine=f301-fujitsu
;;
vxworks960)
basic_machine=i960-wrs
os=-vxworks
;;
vxworks68)
basic_machine=m68k-wrs
os=-vxworks
;;
vxworks29k)
basic_machine=a29k-wrs
os=-vxworks
;;
w65*)
basic_machine=w65-wdc
os=-none
;;
w89k-*)
basic_machine=hppa1.1-winbond
os=-proelf
;;
xbox)
basic_machine=i686-pc
os=-mingw32
;;
xps | xps100)
basic_machine=xps100-honeywell
;;
xscale-* | xscalee[bl]-*)
basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'`
;;
ymp)
basic_machine=ymp-cray
os=-unicos
;;
z8k-*-coff)
basic_machine=z8k-unknown
os=-sim
;;
z80-*-coff)
basic_machine=z80-unknown
os=-sim
;;
none)
basic_machine=none-none
os=-none
;;
# Here we handle the default manufacturer of certain CPU types. It is in
# some cases the only manufacturer, in others, it is the most popular.
w89k)
basic_machine=hppa1.1-winbond
;;
op50n)
basic_machine=hppa1.1-oki
;;
op60c)
basic_machine=hppa1.1-oki
;;
romp)
basic_machine=romp-ibm
;;
mmix)
basic_machine=mmix-knuth
;;
rs6000)
basic_machine=rs6000-ibm
;;
vax)
basic_machine=vax-dec
;;
pdp10)
# there are many clones, so DEC is not a safe bet
basic_machine=pdp10-unknown
;;
pdp11)
basic_machine=pdp11-dec
;;
we32k)
basic_machine=we32k-att
;;
sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele)
basic_machine=sh-unknown
;;
sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
basic_machine=sparc-sun
;;
cydra)
basic_machine=cydra-cydrome
;;
orion)
basic_machine=orion-highlevel
;;
orion105)
basic_machine=clipper-highlevel
;;
mac | mpw | mac-mpw)
basic_machine=m68k-apple
;;
pmac | pmac-mpw)
basic_machine=powerpc-apple
;;
*-unknown)
# Make sure to match an already-canonicalized machine name.
;;
*)
echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
exit 1
;;
esac
# Here we canonicalize certain aliases for manufacturers.
case $basic_machine in
*-digital*)
basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
;;
*-commodore*)
basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
;;
*)
;;
esac
# Decode manufacturer-specific aliases for certain operating systems.
if [ x"$os" != x"" ]
then
case $os in
# First match some system type aliases
# that might get confused with valid system types.
# -solaris* is a basic system type, with this one exception.
-auroraux)
os=-auroraux
;;
-solaris1 | -solaris1.*)
os=`echo $os | sed -e 's|solaris1|sunos4|'`
;;
-solaris)
os=-solaris2
;;
-svr4*)
os=-sysv4
;;
-unixware*)
os=-sysv4.2uw
;;
-gnu/linux*)
os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
;;
# First accept the basic system types.
# The portable systems comes first.
# Each alternative MUST END IN A *, to match a version number.
# -sysv* is not here because it comes later, after sysvr4.
-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
| -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
| -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
| -sym* | -kopensolaris* \
| -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
| -aos* | -aros* \
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
| -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
| -openbsd* | -solidbsd* \
| -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
| -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
| -chorusos* | -chorusrdb* | -cegcc* \
| -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
| -mingw32* | -linux-gnu* | -linux-android* \
| -linux-newlib* | -linux-uclibc* \
| -uxpv* | -beos* | -mpeix* | -udk* \
| -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
| -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
| -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
| -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
| -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
| -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
| -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*)
# Remember, each alternative MUST END IN *, to match a version number.
;;
-qnx*)
case $basic_machine in
x86-* | i*86-*)
;;
*)
os=-nto$os
;;
esac
;;
-nto-qnx*)
;;
-nto*)
os=`echo $os | sed -e 's|nto|nto-qnx|'`
;;
-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
| -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
| -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
;;
-mac*)
os=`echo $os | sed -e 's|mac|macos|'`
;;
-linux-dietlibc)
os=-linux-dietlibc
;;
-linux*)
os=`echo $os | sed -e 's|linux|linux-gnu|'`
;;
-sunos5*)
os=`echo $os | sed -e 's|sunos5|solaris2|'`
;;
-sunos6*)
os=`echo $os | sed -e 's|sunos6|solaris3|'`
;;
-opened*)
os=-openedition
;;
-os400*)
os=-os400
;;
-wince*)
os=-wince
;;
-osfrose*)
os=-osfrose
;;
-osf*)
os=-osf
;;
-utek*)
os=-bsd
;;
-dynix*)
os=-bsd
;;
-acis*)
os=-aos
;;
-atheos*)
os=-atheos
;;
-syllable*)
os=-syllable
;;
-386bsd)
os=-bsd
;;
-ctix* | -uts*)
os=-sysv
;;
-nova*)
os=-rtmk-nova
;;
-ns2 )
os=-nextstep2
;;
-nsk*)
os=-nsk
;;
# Preserve the version number of sinix5.
-sinix5.*)
os=`echo $os | sed -e 's|sinix|sysv|'`
;;
-sinix*)
os=-sysv4
;;
-tpf*)
os=-tpf
;;
-triton*)
os=-sysv3
;;
-oss*)
os=-sysv3
;;
-svr4)
os=-sysv4
;;
-svr3)
os=-sysv3
;;
-sysvr4)
os=-sysv4
;;
# This must come after -sysvr4.
-sysv*)
;;
-ose*)
os=-ose
;;
-es1800*)
os=-ose
;;
-xenix)
os=-xenix
;;
-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
os=-mint
;;
-aros*)
os=-aros
;;
-kaos*)
os=-kaos
;;
-zvmoe)
os=-zvmoe
;;
-dicos*)
os=-dicos
;;
-nacl*)
;;
-none)
;;
*)
# Get rid of the `-' at the beginning of $os.
os=`echo $os | sed 's/[^-]*-//'`
echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
exit 1
;;
esac
else
# Here we handle the default operating systems that come with various machines.
# The value should be what the vendor currently ships out the door with their
# machine or put another way, the most popular os provided with the machine.
# Note that if you're going to try to match "-MANUFACTURER" here (say,
# "-sun"), then you have to tell the case statement up towards the top
# that MANUFACTURER isn't an operating system. Otherwise, code above
# will signal an error saying that MANUFACTURER isn't an operating
# system, and we'll never get to this point.
case $basic_machine in
score-*)
os=-elf
;;
spu-*)
os=-elf
;;
*-acorn)
os=-riscix1.2
;;
arm*-rebel)
os=-linux
;;
arm*-semi)
os=-aout
;;
c4x-* | tic4x-*)
os=-coff
;;
hexagon-*)
os=-elf
;;
tic54x-*)
os=-coff
;;
tic55x-*)
os=-coff
;;
tic6x-*)
os=-coff
;;
# This must come before the *-dec entry.
pdp10-*)
os=-tops20
;;
pdp11-*)
os=-none
;;
*-dec | vax-*)
os=-ultrix4.2
;;
m68*-apollo)
os=-domain
;;
i386-sun)
os=-sunos4.0.2
;;
m68000-sun)
os=-sunos3
;;
m68*-cisco)
os=-aout
;;
mep-*)
os=-elf
;;
mips*-cisco)
os=-elf
;;
mips*-*)
os=-elf
;;
or32-*)
os=-coff
;;
*-tti) # must be before sparc entry or we get the wrong os.
os=-sysv3
;;
sparc-* | *-sun)
os=-sunos4.1.1
;;
*-be)
os=-beos
;;
*-haiku)
os=-haiku
;;
*-ibm)
os=-aix
;;
*-knuth)
os=-mmixware
;;
*-wec)
os=-proelf
;;
*-winbond)
os=-proelf
;;
*-oki)
os=-proelf
;;
*-hp)
os=-hpux
;;
*-hitachi)
os=-hiux
;;
i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
os=-sysv
;;
*-cbm)
os=-amigaos
;;
*-dg)
os=-dgux
;;
*-dolphin)
os=-sysv3
;;
m68k-ccur)
os=-rtu
;;
m88k-omron*)
os=-luna
;;
*-next )
os=-nextstep
;;
*-sequent)
os=-ptx
;;
*-crds)
os=-unos
;;
*-ns)
os=-genix
;;
i370-*)
os=-mvs
;;
*-next)
os=-nextstep3
;;
*-gould)
os=-sysv
;;
*-highlevel)
os=-bsd
;;
*-encore)
os=-bsd
;;
*-sgi)
os=-irix
;;
*-siemens)
os=-sysv4
;;
*-masscomp)
os=-rtu
;;
f30[01]-fujitsu | f700-fujitsu)
os=-uxpv
;;
*-rom68k)
os=-coff
;;
*-*bug)
os=-coff
;;
*-apple)
os=-macos
;;
*-atari*)
os=-mint
;;
*)
os=-none
;;
esac
fi
# Here we handle the case where we know the os, and the CPU type, but not the
# manufacturer. We pick the logical manufacturer.
vendor=unknown
case $basic_machine in
*-unknown)
case $os in
-riscix*)
vendor=acorn
;;
-sunos*)
vendor=sun
;;
-cnk*|-aix*)
vendor=ibm
;;
-beos*)
vendor=be
;;
-hpux*)
vendor=hp
;;
-mpeix*)
vendor=hp
;;
-hiux*)
vendor=hitachi
;;
-unos*)
vendor=crds
;;
-dgux*)
vendor=dg
;;
-luna*)
vendor=omron
;;
-genix*)
vendor=ns
;;
-mvs* | -opened*)
vendor=ibm
;;
-os400*)
vendor=ibm
;;
-ptx*)
vendor=sequent
;;
-tpf*)
vendor=ibm
;;
-vxsim* | -vxworks* | -windiss*)
vendor=wrs
;;
-aux*)
vendor=apple
;;
-hms*)
vendor=hitachi
;;
-mpw* | -macos*)
vendor=apple
;;
-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
vendor=atari
;;
-vos*)
vendor=stratus
;;
esac
basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
;;
esac
echo $basic_machine$os
exit
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "timestamp='"
# time-stamp-format: "%:y-%02m-%02d"
# time-stamp-end: "'"
# End:
PHYLIPNEW-3.69.650/src/ 0002775 0001750 0001750 00000000000 12171071712 011136 5 0000000 0000000 PHYLIPNEW-3.69.650/src/retree.c 0000664 0001750 0001750 00000233755 11305225544 012527 0000000 0000000
#include "phylip.h"
#include "moves.h"
/* version 3.6. (c) Copyright 1993-2008 by the University of Washington.
Written by Joseph Felsenstein and Andrew Keeffe. Permission is granted to
copy and use this program provided no fee is charged for it and provided
that this copyright notice is not removed. */
/* maximum number of species */
#define maxsp 5000
/* size of pointer array. >= 2*maxsp - 1 */
/* (this can be large without eating memory */
#define maxsz 9999
#define overr 4
#define which 1
AjPPhyloTree* phylotrees = NULL;
typedef enum {valid, remoov, quit} reslttype;
typedef enum {
horiz, vert, up, updel, ch_over, upcorner, midcorner, downcorner, aa, cc,
gg, tt, deleted
} chartype;
typedef struct treeset_t {
node *root;
pointarray nodep;
long nonodes;
boolean waswritten, hasmult, haslengths, nolengths, initialized;
} treeset_t;
treeset_t treesets[2];
treeset_t simplifiedtree;
typedef enum { arb, use, spec } howtree;
typedef enum {beforenode, atnode} movet;
movet fromtype;
#ifndef OLDC
/* function prototypes */
void initretreenode(node **, node **, node *, long, long, long *,
long *, initops, pointarray, pointarray, Char *, Char *, char **);
void gdispose(node *);
void maketriad(node **, long);
void maketip(node **, long);
void copynode(node *, node *);
node *copytrav(node *);
void copytree(void);
//void getoptions(void);
void emboss_getoptions(char *pgm, int argc, char *argv[]);
void configure(void);
void prefix(chartype);
void postfix(chartype);
void ltrav(node *, boolean *);
boolean ifhaslengths(void);
void add_at(node *, node *, node *);
void add_before(node *, node *);
void add_child(node *, node *);
void re_move(node **, node **);
void reroot(node *);
void ltrav_(node *, double, double, double *, long *, long *);
void precoord(node *, boolean *, double *, long *);
void coordinates(node *, double, long *, long *, double *);
void flatcoordinates(node *, long *);
void grwrite(chartype, long, long *);
void drawline(long, node *, boolean *);
void printree(void);
void togglelengths(void);
void arbitree(void);
void yourtree(void);
void buildtree(void);
void unbuildtree(void);
void retree_help(void);
void consolidatetree(long);
void rearrange(void);
boolean any_deleted(node *);
void fliptrav(node *, boolean);
void flip(long);
void transpose(long);
void ifdeltrav(node *, boolean *);
double oltrav(node *);
void outlength(void);
void midpoint(void);
void deltrav(node *, boolean );
void reg_del(node *, boolean);
boolean isdeleted(long);
void deletebranch(void);
void restorebranch(void);
void del_or_restore(void);
void undo(void);
void treetrav(node *);
void simcopynode(node *, node *);
node *simcopytrav(node *);
void simcopytree(void);
void writebranchlength(double);
void treeout(node *, boolean, double, long);
void maketemptriad(node **, long);
void roottreeout(boolean *);
void notrootedtorooted(void);
void rootedtonotrooted(void);
void treewrite(boolean *);
void retree_window(adjwindow);
void getlength(double *, reslttype *, boolean *);
void changelength(void);
void changename(void);
void clade(void);
void changeoutgroup(void);
void redisplay(void);
void treeconstruct(void);
void fill_del(node*p);
/* function prototypes */
#endif
node *root, *garbage;
long nonodes, outgrno, screenwidth, vscreenwidth,
screenlines, col, treenumber, leftedge, topedge, treelines,
hscroll, vscroll, scrollinc, whichtree, othertree,
numtrees, treesread;
double trweight;
boolean waswritten, onfirsttree, hasmult, haslengths,
nolengths, nexus, xmltree;
node **treeone, **treetwo;
pointarray nodep; /* pointers to all nodes in current tree */
node *grbg;
boolean reversed[14];
boolean graphic[14];
unsigned char cch[14];
howtree how;
char intreename[FNMLNGTH];
const char* outtreename;
AjPFile embossouttree;
boolean subtree, written, readnext;
node *nuroot;
Char ch;
boolean delarray[maxsz];
void initretreenode(node **p, node **grbg, node *q, long len,
long nodei, long *ntips, long *parens, initops whichinit,
pointarray treenode, pointarray nodep, Char *str,
Char *ch, char** treestr)
{
/* initializes a node */
long i;
boolean minusread;
double valyew, divisor;
switch (whichinit) {
case bottom:
gnu(grbg, p);
(*p)->index = nodei;
(*p)->tip = false;
(*p)->deleted=false;
(*p)->deadend=false;
(*p)->onebranch=false;
(*p)->onebranchhaslength=false;
for (i=0;inayme[i] = '\0';
nodep[(*p)->index - 1] = (*p);
break;
case nonbottom:
gnu(grbg, p);
(*p)->index = nodei;
break;
case hslength:
if ((*p)->back) {
(*p)->back->back = *p;
(*p)->haslength = (*p)->back->haslength;
if ((*p)->haslength)
(*p)->length = (*p)->back->length;
}
break;
case tip:
(*ntips)++;
gnu(grbg, p);
nodep[(*ntips) - 1] = *p;
(*p)->index = *ntips;
(*p)->tip = true;
(*p)->hasname = true;
strncpy ((*p)->nayme, str, MAXNCH);
break;
case length:
(*p)->haslength = true;
if ((*p)->back != NULL)
(*p)->back->haslength = (*p)->haslength;
processlength(&valyew, &divisor, ch,
&minusread, treestr, parens);
if (!minusread)
(*p)->length = valyew / divisor;
else
(*p)->length = 0.0;
(*p)->back = q;
if (haslengths && q != NULL) {
(*p)->back->haslength = (*p)->haslength;
(*p)->back->length = (*p)->length;
}
break;
case hsnolength:
haslengths = (haslengths && q == NULL);
(*p)->haslength = false;
(*p)->back = q;
break;
default: /*cases iter, treewt, unttrwt */
break; /*should not occur */
}
} /* initretreenode */
void gdispose(node *p)
{
/* go through tree throwing away nodes */
node *q, *r;
if (p->tip)
return;
q = p->next;
while (q != p) {
gdispose(q->back);
q->tip = false;
q->hasname = false;
q->haslength = false;
r = q;
q = q->next;
chuck(&grbg, r);
}
q->tip = false;
q->hasname = false;
q->haslength = false;
chuck(&grbg, q);
} /* gdispose */
void maketriad(node **p, long index)
{
/* Initiate an internal node with stubs for two children */
long i, j;
node *q;
q = NULL;
for (i = 1; i <= 3; i++) {
gnu(&grbg, p);
(*p)->index = index;
(*p)->hasname = false;
(*p)->haslength = false;
(*p)->deleted=false;
(*p)->deadend=false;
(*p)->onebranch=false;
(*p)->onebranchhaslength=false;
for (j=0;jnayme[j] = '\0';
(*p)->next = q;
q = *p;
}
(*p)->next->next->next = *p;
q = (*p)->next;
while (*p != q) {
(*p)->back = NULL;
(*p)->tip = false;
*p = (*p)->next;
}
nodep[index - 1] = *p;
} /* maketriad */
void maketip(node **p, long index)
{
/* Initiate a tip node */
gnu(&grbg, p);
(*p)->index = index;
(*p)->tip = true;
(*p)->hasname = false;
(*p)->haslength = false;
nodep[index - 1] = *p;
} /* maketip */
void copynode(node *fromnode, node *tonode)
{
/* Copy the contents of a node from fromnode to tonode. */
int i;
tonode->index = fromnode->index;
tonode->deleted = fromnode->deleted;
tonode->tip = fromnode->tip;
tonode->hasname = fromnode->hasname;
if (fromnode->hasname)
for (i=0;inayme[i] = fromnode->nayme[i];
tonode->haslength = fromnode->haslength;
if (fromnode->haslength)
tonode->length = fromnode->length;
} /* copynode */
node *copytrav(node *p)
{
/* Traverse the tree from p on down, copying nodes to the other tree */
node *q, *newnode, *newnextnode, *temp;
gnu(&grbg, &newnode);
copynode(p,newnode);
if (nodep[p->index-1] == p)
treesets[othertree].nodep[p->index-1] = newnode;
/* if this is a tip, return now */
if (p->tip)
return newnode;
/* go around the ring, copying as we go */
q = p->next;
gnu(&grbg, &newnextnode);
copynode(q, newnextnode);
newnode->next = newnextnode;
do {
newnextnode->back = copytrav(q->back);
newnextnode->back->back = newnextnode;
q = q->next;
if (q == p)
newnextnode->next = newnode;
else {
temp = newnextnode;
gnu(&grbg, &newnextnode);
copynode(q, newnextnode);
temp->next = newnextnode;
}
} while (q != p);
return newnode;
} /* copytrav */
void copytree()
{
/* Make a complete copy of the current tree for undo purposes */
if (whichtree == 1)
othertree = 0;
else
othertree = 1;
treesets[othertree].root = copytrav(root);
treesets[othertree].nonodes = nonodes;
treesets[othertree].waswritten = waswritten;
treesets[othertree].hasmult = hasmult;
treesets[othertree].haslengths = haslengths;
treesets[othertree].nolengths = nolengths;
treesets[othertree].initialized = true;
} /* copytree */
void emboss_getoptions(char *pgm, int argc, char *argv[])
{
AjPStr initialtree = NULL;
AjPStr format = NULL;
how = use;
outgrno = 1;
onfirsttree = true;
screenlines = 24;
screenwidth = 80;
vscreenwidth = 80;
nexus = false;
xmltree = false;
embInitPV(pgm, argc, argv, "PHYLIPNEW",VERSION);
phylotrees = ajAcdGetTree("intreefile");
if(ajStrMatchC(initialtree, "a")) how = arb;
else if(ajStrMatchC(initialtree, "u")) how = use;
else if(ajStrMatchC(initialtree, "s")) how = spec;
format = ajAcdGetListSingle("format");
if(ajStrMatchC(format, "n")) nexus = true;
else if(ajStrMatchC(format, "x")) xmltree = true;
screenwidth = ajAcdGetInt("screenwidth");
vscreenwidth = ajAcdGetInt("vscreenwidth");
screenlines = ajAcdGetInt("screenlines");
if (scrollinc < screenwidth / 2.0)
hscroll = scrollinc;
else
hscroll = screenwidth / 2;
if (scrollinc < screenlines / 2.0)
vscroll = scrollinc;
else
vscroll = screenlines / 2;
embossouttree = ajAcdGetOutfile("outtreefile");
emboss_openfile(embossouttree, &outtree, &outtreename);
} /* emboss_getoptions */
void configure()
{
/* configure to machine -- set up special characters */
chartype a;
for (a = horiz; (long)a <= (long)deleted; a = (chartype)((long)a + 1))
reversed[(long)a] = false;
for (a = horiz; (long)a <= (long)deleted; a = (chartype)((long)a + 1))
graphic[(long)a] = false;
cch[(long)deleted] = '.';
cch[(long)updel] = ':';
if (ibmpc) {
cch[(long)horiz] = '>';
cch[(long)vert] = 186;
graphic[(long)vert] = true;
cch[(long)up] = 186;
graphic[(long)up] = true;
cch[(long)ch_over] = 205;
graphic[(long)ch_over] = true;
cch[(long)upcorner] = 200;
graphic[(long)upcorner] = true;
cch[(long)midcorner] = 204;
graphic[(long)midcorner] = true;
cch[(long)downcorner] = 201;
graphic[(long)downcorner] = true;
return;
}
if (ansi) {
cch[(long)horiz] = '>';
cch[(long)vert] = cch[(long)horiz];
reversed[(long)vert] = true;
cch[(long)up] = 'x';
graphic[(long)up] = true;
cch[(long)ch_over] = 'q';
graphic[(long)ch_over] = true;
cch[(long)upcorner] = 'm';
graphic[(long)upcorner] = true;
cch[(long)midcorner] = 't';
graphic[(long)midcorner] = true;
cch[(long)downcorner] = 'l';
graphic[(long)downcorner] = true;
return;
}
cch[(long)horiz] = '>';
cch[(long)vert] = ' ';
cch[(long)up] = '!';
cch[(long)upcorner] = '`';
cch[(long)midcorner] = '+';
cch[(long)downcorner] = ',';
cch[(long)ch_over] = '-';
} /* configure */
void prefix(chartype a)
{
/* give prefix appropriate for this character */
if (reversed[(long)a])
prereverse(ansi);
if (graphic[(long)a])
pregraph2(ansi);
} /* prefix */
void postfix(chartype a)
{
/* give postfix appropriate for this character */
if (reversed[(long)a])
postreverse(ansi);
if (graphic[(long)a])
postgraph2(ansi);
} /* postfix */
void ltrav(node *p, boolean *localhl)
{
/* Traversal function for ifhaslengths() */
node *q;
if (p->tip) {
(*localhl) = ((*localhl) && p->haslength);
return;
}
q = p->next;
do {
(*localhl) = ((*localhl) && q->haslength);
if ((*localhl))
ltrav(q->back, localhl);
q = q->next;
} while (p != q);
} /* ltrav */
boolean ifhaslengths()
{
/* return true if every branch in tree has a length */
boolean localhl;
localhl = true;
ltrav(root, &localhl);
return localhl;
} /* ifhaslengths */
void add_at(node *below, node *newtip, node *newfork)
{
/* inserts the nodes newfork and its left descendant, newtip,
to the tree. below becomes newfork's right descendant */
node *leftdesc, *rtdesc;
double length;
if (below != nodep[below->index - 1])
below = nodep[below->index - 1];
if (newfork == NULL) {
nonodes++;
maketriad (&newfork, nonodes);
if (haslengths) {
newfork->haslength = true;
newfork->next->haslength = true;
newfork->next->next->haslength = true;
}
}
if (below->back != NULL) {
below->back->back = newfork;
}
newfork->back = below->back;
leftdesc = newtip;
rtdesc = below;
rtdesc->back = newfork->next->next;
newfork->next->next->back = rtdesc;
newfork->next->back = leftdesc;
leftdesc->back = newfork->next;
if (root == below)
root = newfork;
root->back = NULL;
if (!haslengths)
return;
if (newfork->back != NULL) {
length = newfork->back->length / 2.0;
newfork->length = length;
newfork->back->length = length;
below->length = length;
below->back->length = length;
} else {
length = newtip->length / 2.0;
newtip->length = length;
newtip->back->length = length;
below->length = length;
below->back->length = length;
below->haslength = true;
}
newtip->back->length = newtip->length;
} /* add_at */
void add_before(node *atnode, node *newtip)
{
/* inserts the node newtip together with its ancestral fork
into the tree next to the node atnode. */
/*xx ?? debug what to do if no ancestral node -- have to create one */
/*xx this case is handled by add_at. However, add_at does not account for
when there is more than one sibling for the relocated newtip */
node *q;
if (atnode != nodep[atnode->index - 1])
atnode = nodep[atnode->index - 1];
q = nodep[newtip->index-1]->back;
if (q != NULL) {
q = nodep[q->index-1];
if (newtip == q->next->next->back) {
q->next->back = newtip;
newtip->back = q->next;
q->next->next->back = NULL;
}
}
if (newtip->back != NULL) {
add_at(atnode, newtip, nodep[newtip->back->index-1]);
} else {
add_at(atnode, newtip, NULL);
}
} /* add_before */
void add_child(node *parent, node *newchild)
{
/* adds the node newchild into the tree as the last child of parent */
int i;
node *newnode, *q;
if (parent != nodep[parent->index - 1])
parent = nodep[parent->index - 1];
gnu(&grbg, &newnode);
newnode->tip = false;
newnode->deleted=false;
newnode->deadend=false;
newnode->onebranch=false;
newnode->onebranchhaslength=false;
for (i=0;inayme[i] = '\0';
newnode->index = parent->index;
q = parent;
do {
q = q->next;
} while (q->next != parent);
newnode->next = parent;
q->next = newnode;
newnode->back = newchild;
newchild->back = newnode;
if (newchild->haslength) {
newnode->length = newchild->length;
newnode->haslength = true;
} else
newnode->haslength = false;
} /* add_child */
void re_move(node **item, node **fork)
{
/* Removes node item from the tree. If item has one sibling,
removes its ancestor, fork, from the tree as well and attach
item's sib to fork's ancestor. In this case, it returns a pointer
to the removed fork node which is still attached to item.
*/
node *p =NULL, *q;
int nodecount;
if ((*item)->back == NULL) {
*fork = NULL;
return;
}
*fork = nodep[(*item)->back->index - 1];
nodecount = 0;
if ((*fork)->next->back == *item)
p = *fork;
q = (*fork)->next;
do {
nodecount++;
if (q->next->back == *item)
p = q;
q = q->next;
} while (*fork != q);
if (nodecount > 2)
{
fromtype = atnode;
p->next = (*item)->back->next;
chuck(&grbg, (*item)->back);
(*item)->back = NULL;
/*xx*/ *fork = NULL;
} else {
/* traditional (binary tree) remove code */
if (*item == (*fork)->next->back) {
if (root == *fork)
root = (*fork)->next->next->back;
} else {
if (root == *fork)
root = (*fork)->next->back;
}
fromtype = beforenode;
/* stitch nodes together, leaving out item */
p = (*item)->back->next->back;
q = (*item)->back->next->next->back;
if (p != NULL)
p->back = q;
if (q != NULL)
q->back = p;
if (haslengths) {
if (p != NULL && q != NULL) {
p->length += q->length;
q->length = p->length;
} else
(*item)->length = (*fork)->next->length + (*fork)->next->next->length;
}
(*fork)->back = NULL;
p = (*fork)->next;
while (p != *fork) {
p->back = NULL;
p = p->next;
}
(*item)->back = NULL;
} /* endif nodecount > 2 else */
} /* re_move */
void reroot(node *outgroup)
{
/* Reorient tree so that outgroup is by itself on the left of the root */
node *p, *q, *r;
long nodecount = 0;
double templen;
q = root->next;
do { /* when this loop exits, p points to the internal */
p = q; /* node to the right of root */
nodecount++;
q = p->next;
} while (q != root);
r = p;
/* There is no point in proceeding if
1. outgroup is a child of root, and
2. the tree bifurcates at the root.
*/
if((outgroup->back->index == root->index) && !(nodecount > 2))
return;
/* reorient nodep array
The nodep array must point to the ring member of each ring
that is closest to the root. The while loop changes the ring member
pointed to by nodep[] for those nodes that will have their
orientation changed by the reroot operation.
*/
p = outgroup->back;
while (p->index != root->index) {
q = nodep[p->index - 1]->back;
nodep[p->index - 1] = p;
p = q;
}
if (nodecount > 2)
nodep[p->index - 1] = p;
/* If nodecount > 2, the current node ring to which root is pointing
will remain in place and root will point somewhere else. */
/* detach root from old location */
if (nodecount > 2) {
r->next = root->next;
root->next = NULL;
nonodes++;
maketriad(&root, nonodes);
if (haslengths) {
/* root->haslength remains false, or else treeout() will generate
a bogus extra length */
root->next->haslength = true;
root->next->next->haslength = true;
}
} else { /* if (nodecount > 2) else */
q = root->next;
q->back->back = r->back;
r->back->back = q->back;
if (haslengths) {
r->back->length = r->back->length + q->back->length;
q->back->length = r->back->length;
}
} /* if (nodecount > 2) endif */
/* tie root into new location */
root->next->back = outgroup;
root->next->next->back = outgroup->back;
outgroup->back->back = root->next->next;
outgroup->back = root->next;
/* place root equidistant between left child (outgroup) and
right child by dividing outgroup's length */
if (haslengths) {
templen = outgroup->length / 2.0;
outgroup->length = templen;
outgroup->back->length = templen;
root->next->next->length = templen;
root->next->next->back->length = templen;
}
} /* reroot */
void ltrav_(node *p, double lengthsum, double lmin, double *tipmax,
long *across, long *maxchar)
{
node *q;
long rchar, nl;
double sublength;
if (p->tip) {
if (lengthsum > (*tipmax))
(*tipmax) = lengthsum;
if (lmin == 0.0)
return;
rchar = (long)(lengthsum / (*tipmax) * (*across) + 0.5);
nl = strlen(nodep[p->index - 1]->nayme);
if (rchar + nl > (*maxchar))
(*across) = (*maxchar) - (long)(nl * (*tipmax) / lengthsum + 0.5);
return;
}
q = p->next;
do {
if (q->length >= lmin)
sublength = q->length;
else
sublength = lmin;
ltrav_(q->back, lengthsum + sublength, lmin, tipmax, across, maxchar);
q = q->next;
} while (p != q);
} /* ltrav */
void precoord(node *nuroot,boolean *subtree,double *tipmax,long *across)
{
/* set tipmax and across so that tree is scaled to screenwidth */
double oldtipmax, minimum;
long i, maxchar;
(*tipmax) = 0.0;
if ((*subtree))
maxchar = vscreenwidth - 13;
else
maxchar = vscreenwidth - 5;
(*across) = maxchar;
ltrav_(nuroot, 0.0, 0.0, tipmax, across, &maxchar);
i = 0;
do {
oldtipmax = (*tipmax);
minimum = 3.0 / (*across) * (*tipmax);
ltrav_(nuroot, 0.0, minimum, tipmax, across, &maxchar);
i++;
} while (fabs((*tipmax) - oldtipmax) > 0.01 * oldtipmax && i <= 40);
} /* precoord */
void coordinates(node *p, double lengthsum, long *across, long *tipy,
double *tipmax)
{
/* establishes coordinates of nodes for display with lengths */
node *q, *first, *last;
if (p->tip) {
p->xcoord = (long)((*across) * lengthsum / (*tipmax) + 0.5);
p->ycoord = (*tipy);
p->ymin = (*tipy);
p->ymax = (*tipy);
(*tipy) += down;
return;
}
q = p->next;
do {
coordinates(q->back, lengthsum + q->length, across, tipy, tipmax);
q = q->next;
} while (p != q);
first = p->next->back;
q = p;
while (q->next != p)
q = q->next;
last = q->back;
p->xcoord = (long)((*across) * lengthsum / (*tipmax) + 0.5);
if (p == root) {
if (root->next->next->next == root)
p->ycoord = (first->ycoord + last->ycoord) / 2;
else
p->ycoord = p->next->next->back->ycoord;
}
else
p->ycoord = (first->ycoord + last->ycoord) / 2;
p->ymin = first->ymin;
p->ymax = last->ymax;
} /* coordinates */
void flatcoordinates(node *p, long *tipy)
{
/* establishes coordinates of nodes for display without lengths */
node *q, *first, *last;
if (p->tip) {
p->xcoord = 0;
p->ycoord = (*tipy);
p->ymin = (*tipy);
p->ymax = (*tipy);
(*tipy) += down;
return;
}
q = p->next;
do {
flatcoordinates(q->back, tipy);
q = q->next;
} while (p != q);
first = p->next->back;
q = p->next;
while (q->next != p)
q = q->next;
last = q->back;
p->xcoord = (last->ymax - first->ymin) * 3 / 2;
if (p == root) {
if (root->next->next->next == root)
p->ycoord = (first->ycoord + last->ycoord) / 2;
else
p->ycoord = p->next->next->back->ycoord;
}
else
p->ycoord = (first->ycoord + last->ycoord) / 2;
p->ymin = first->ymin;
p->ymax = last->ymax;
} /* flatcoordinates */
void grwrite(chartype c, long num, long *pos)
{
long i;
prefix(c);
for (i = 1; i <= num; i++) {
if ((*pos) >= leftedge && (*pos) - leftedge + 1 < screenwidth)
putchar(cch[(long)c]);
(*pos)++;
}
postfix(c);
} /* grwrite */
void drawline(long i, node *nuroot, boolean *subtree)
{
/* draws one row of the tree diagram by moving up tree */
long pos;
node *p, *q, *r, *s, *first =NULL, *last =NULL;
long n, j;
long up_nondel, down_nondel;
boolean extra, done;
chartype c, d;
pos = 1;
p = nuroot;
q = nuroot;
extra = false;
if (i == (long)p->ycoord && (p == root || (*subtree))) {
c = ch_over;
if ((*subtree))
stwrite("Subtree:", 8, &pos, leftedge, screenwidth);
if (p->index >= 100)
nnwrite(p->index, 3, &pos, leftedge, screenwidth);
else if (p->index >= 10) {
grwrite(c, 1, &pos);
nnwrite(p->index, 2, &pos, leftedge, screenwidth);
} else {
grwrite(c, 2, &pos);
nnwrite(p->index, 1, &pos, leftedge, screenwidth);
}
extra = true;
} else {
if ((*subtree))
stwrite(" ", 10, &pos, leftedge, screenwidth);
else
stwrite(" ", 2, &pos, leftedge, screenwidth);
}
do {
if (!p->tip) {
r = p->next;
done = false;
do {
if (i >= r->back->ymin && i <= r->back->ymax) {
q = r->back;
done = true;
}
r = r->next;
} while (!(done || r == p));
first = p->next->back;
r = p->next;
while (r->next != p)
r = r->next;
last = r->back;
}
done = (p == q);
if (haslengths && !nolengths)
n = (long)(q->xcoord - p->xcoord);
else
n = (long)(p->xcoord - q->xcoord);
if (n < 3 && !q->tip)
n = 3;
if (extra) {
n--;
extra = false;
}
if ((long)q->ycoord == i && !done) {
c = ch_over;
if (!haslengths && !q->haslength)
c = horiz;
if (q->deleted)
c = deleted;
if (q == first)
d = downcorner;
else if (q == last)
d = upcorner;
else if ((long)q->ycoord == (long)p->ycoord)
d = c;
else
d = midcorner;
if (n > 1 || q->tip) {
grwrite(d, 1, &pos);
grwrite(c, n - 3, &pos);
}
if (q->index >= 100)
nnwrite(q->index, 3, &pos, leftedge, screenwidth);
else if (q->index >= 10) {
grwrite(c, 1, &pos);
nnwrite(q->index, 2, &pos, leftedge, screenwidth);
} else {
grwrite(c, 2, &pos);
nnwrite(q->index, 1, &pos, leftedge, screenwidth);
}
extra = true;
} else if (!q->tip) {
if ((long)last->ycoord > i && (long)first->ycoord < i &&
i != (long)p->ycoord) {
c = up;
if(p->deleted)
c = updel;
if (!p->tip) {
up_nondel = 0;
down_nondel = 0;
r = p->next;
do {
s = r->back;
if ((long)s->ycoord < (long)p->ycoord && !s->deleted)
up_nondel = (long)s->ycoord;
if (s->ycoord > p->ycoord && !s->deleted &&
(down_nondel == 0))
down_nondel = (long)s->ycoord;
if (i < (long)p->ycoord && s->deleted && i > (long)s->ycoord)
c = updel;
if (i > (long)p->ycoord && s->deleted && i < (long)s->ycoord)
c = updel;
r = r->next;
} while (r != p);
if ((up_nondel != 0) && i < (long)p->ycoord && i > up_nondel)
c = up;
if ((down_nondel != 0) && i > (long)p->ycoord && i < down_nondel)
c = up;
}
grwrite(c, 1, &pos);
chwrite(' ', n - 1, &pos, leftedge, screenwidth);
} else
chwrite(' ', n, &pos, leftedge, screenwidth);
} else
chwrite(' ', n, &pos, leftedge, screenwidth);
if (p != q)
p = q;
} while (!done);
if ((long)p->ycoord == i && p->tip) {
if (p->hasname) {
n = 0;
for (j = 1; j <= MAXNCH; j++) {
if (nodep[p->index - 1]->nayme[j - 1] != '\0')
n = j;
}
chwrite(':', 1, &pos, leftedge, screenwidth);
for (j = 0; j < n; j++)
chwrite(nodep[p->index - 1]->nayme[j],
1, &pos, leftedge, screenwidth);
}
}
putchar('\n');
} /* drawline */
void printree()
{
/* prints out diagram of the tree */
long across;
long tipy;
double tipmax;
long i, dow, vmargin;
haslengths = ifhaslengths();
if (!subtree)
nuroot = root;
cleerhome();
tipy = 1;
dow = down;
if (spp * dow > screenlines && !subtree) {
dow--;
}
if (haslengths && !nolengths) {
precoord(nuroot, &subtree, &tipmax, &across);
/* protect coordinates() from div/0 errors if user decides to
examine a tip as a subtree */
if (tipmax == 0)
tipmax = 0.01;
coordinates(nuroot, 0.0, &across, &tipy, &tipmax);
} else
flatcoordinates(nuroot, &tipy);
vmargin = 2;
treelines = tipy - dow;
if (topedge != 1) {
printf("** %ld lines above screen **\n", topedge - 1);
vmargin++;
}
if ((treelines - topedge + 1) > (screenlines - vmargin))
vmargin++;
for (i = 1; i <= treelines; i++) {
if (i >= topedge && i < topedge + screenlines - vmargin)
drawline(i, nuroot,&subtree);
}
if (leftedge > 1)
printf("** %ld characters to left of screen ", leftedge);
if ((treelines - topedge + 1) > (screenlines - vmargin)) {
printf("** %ld", treelines - (topedge - 1 + screenlines - vmargin));
printf(" lines below screen **\n");
}
if (treelines - topedge + vmargin + 1 < screenlines)
putchar('\n');
} /* printree */
void togglelengths()
{
nolengths = !nolengths;
printree();
} /* togglengths */
void arbitree()
{
long i;
node *newtip, *newfork;
spp = ajAcdGetInt("spp");
nonodes = spp * 2 - 1;
maketip(&root, 1);
maketip(&newtip, 2);
maketriad(&newfork, spp + 1);
add_at(root, newtip, newfork);
for (i = 3; i <= spp; i++) {
maketip(&newtip, i);
maketriad(&newfork, spp + i - 1);
add_at(nodep[spp + i - 3], newtip, newfork);
}
} /* arbitree */
void yourtree()
{
long uniquearray[maxsz];
long uniqueindex = 0;
long i, j, k, k_max=0, maxinput;
boolean ok, done;
node *newtip, *newfork;
Char ch;
uniquearray[0] = 0;
spp = 2;
nonodes = spp * 2 - 1;
maketip(&root, 1);
maketip(&newtip, 2);
maketriad(&newfork, spp + 3);
add_at(root, newtip, newfork);
i = 2;
maxinput = 1;
k_max = 5;
do {
i++;
printree();
printf("Enter 0 to stop building tree.\n");
printf("Add species%3ld", i);
do {
printf("\n at or before which node (type number): ");
inpnum(&j, &ok);
ok = (ok && ((unsigned long)j < i || (j > spp + 2 && j < spp + i + 1)));
if (!ok)
printf("Impossible number. Please try again:\n");
maxinput++;
if (maxinput == 100) {
printf("ERROR: too many tries at choosing number\n");
embExitBad();
}
} while (!ok);
maxinput = 1;
if (j >= i) { /* has user chosen a non-tip? if so, offer choice */
do {
printf(" Insert at node (A) or before node (B)? ");
#ifdef WIN32
phyFillScreenColor();
#endif
fflush(stdout);
scanf("%c%*[^\n]", &ch);
getchar();
if (ch == '\n')
ch = ' ';
ch = isupper((int)ch) ? ch : toupper((int)ch);
maxinput++;
if (maxinput == 100) {
printf("ERROR: too many tries at choosing option\n");
embExitBad();
}
} while (ch != 'A' && ch != 'B');
}
else ch = 'B'; /* if user has chosen a tip, set Before */
if (j != 0) {
if (ch == 'A') {
if (!nodep[j - 1]->tip) {
maketip(&newtip, i);
add_child(nodep[j - 1], nodep[i - 1]);
}
} else {
maketip(&newtip, i);
maketriad(&newfork, spp + i + 1);
nodep[i-1]->back = newfork;
newfork->back = nodep[i-1];
add_before(nodep[j - 1], nodep[i - 1]);
} /* endif (before or at node) */
}
done = (j == 0);
if (!done) {
if (ch == 'B')
k = spp * 2 + 3;
else
k = spp * 2 + 2;
k_max = k;
do {
if (nodep[k - 2] != NULL) {
nodep[k - 1] = nodep[k - 2];
nodep[k - 1]->index = k;
nodep[k - 1]->next->index = k;
nodep[k - 1]->next->next->index = k;
}
k--;
} while (k != spp + 3);
if (j > spp + 1)
j++;
spp++;
nonodes = spp * 2 - 1;
}
} while (!done);
for (i = spp + 1; i <= k_max; i++) {
if ((nodep[i - 1] != nodep[i]) && (nodep[i - 1] != NULL)) {
uniquearray[uniqueindex++] = i;
uniquearray[uniqueindex] = 0;
}
}
for ( i = 0; uniquearray[i] != 0; i++) {
nodep[spp + i] = nodep[uniquearray[i] - 1];
nodep[spp + i]->index = spp + i + 1;
nodep[spp + i]->next->index = spp + i + 1;
nodep[spp + i]->next->next->index = spp + i + 1;
}
for (i = spp + uniqueindex; i <= k_max; i++)
nodep[i] = NULL;
nonodes = spp * 2 - 1;
} /* yourtree */
void buildtree(void)
{
/* variables needed to be passed to treeread() */
long nextnode = 0;
pointarray dummy_treenode=NULL; /* Ignore what happens to this */
boolean goteof = false;
boolean haslengths = false;
boolean firsttree;
node *p, *q;
long nodecount = 0;
char* treestr;
/* These assignments moved from treeconstruct -- they seem to happen
only here. */
/*xx treeone & treetwo assignments should probably happen in
treeconstruct. Memory leak if user reads multiple trees. */
treeone = (node **)Malloc(maxsz*sizeof(node *));
treetwo = (node **)Malloc(maxsz*sizeof(node *));
simplifiedtree.nodep = (node **)Malloc(maxsz*sizeof(node *));
subtree = false;
topedge = 1;
leftedge = 1;
switch (how) {
case arb:
nodep = treeone;
treesets[othertree].nodep = treetwo;
arbitree();
break;
case use:
printf("\nReading tree file ...\n\n");
if (!readnext) {
/* This is the first time through here, act accordingly */
firsttree = true;
treesread = 0;
} else {
/* This isn't the first time through here ... */
firsttree = false;
}
treestr = ajStrGetuniquePtr(&phylotrees[treesread]->Tree);
allocate_nodep(&nodep, treestr, &spp);
treesets[whichtree].nodep = nodep;
if (firsttree)
nayme = (naym *)Malloc(spp*sizeof(naym));
treeread(&treestr, &root, dummy_treenode, &goteof, &firsttree, nodep,
&nextnode, &haslengths, &grbg, initretreenode,true,-1);
nonodes = nextnode;
treesread++;
treesets[othertree].nodep = treetwo;
break;
case spec:
nodep = treeone;
treesets[othertree].nodep = treetwo;
yourtree();
break;
}
q = root->next;
do {
p = q;
nodecount++;
q = p->next;
} while (q != root);
outgrno = root->next->back->index;
if(!(nodecount > 2)) {
reroot(nodep[outgrno - 1]);
}
} /* buildtree */
void unbuildtree()
{
/* throw all nodes of the tree onto the garbage heap */
long i;
gdispose(root);
for (i = 0; i < nonodes; i++)
nodep[i] = NULL;
} /* unbuildtree */
void retree_help()
{
/* display help information */
char tmp[100];
printf("\n\n . Redisplay the same tree again\n");
if (haslengths) {
printf(" = Redisplay the same tree with");
if (!nolengths)
printf("out/with");
else
printf("/without");
printf(" lengths\n");
}
printf(" U Undo the most recent change in the tree\n");
printf(" W Write tree to a file\n");
printf(" + Read next tree from file (may blow up if none is there)\n");
printf("\n");
printf(" R Rearrange a tree by moving a node or group\n");
printf(" O select an Outgroup for the tree\n");
if (haslengths)
printf(" M Midpoint root the tree\n");
printf(" T Transpose immediate branches at a node\n");
printf(" F Flip (rotate) subtree at a node\n");
printf(" D Delete or restore nodes\n");
printf(" B Change or specify the length of a branch\n");
printf(" N Change or specify the name(s) of tip(s)\n");
printf("\n");
printf(" H Move viewing window to the left\n");
printf(" J Move viewing window downward\n");
printf(" K Move viewing window upward\n");
printf(" L Move viewing window to the right\n");
printf(" C show only one Clade (subtree) (might be useful if tree is ");
printf("too big)\n");
printf(" ? Help (this screen)\n");
printf(" Q (Quit) Exit from program\n");
printf(" X Exit from program\n\n");
printf(" TO CONTINUE, PRESS ON THE Return OR Enter KEY");
getstryng(tmp);
printree();
} /* retree_help */
void consolidatetree(long index)
{
node *start, *r, *q;
int i;
start = nodep[index - 1];
q = start->next;
while (q != start) {
r = q;
q = q->next;
chuck(&grbg, r);
}
chuck(&grbg, q);
i = index;
while (nodep[i-1] != NULL) {
r = nodep[i - 1];
if (!(r->tip))
r->index--;
if (!(r->tip)) {
q = r->next;
do {
q->index--;
q = q->next;
} while (r != q && q != NULL);
}
nodep[i - 1] = nodep[i];
i++;
}
nonodes--;
} /* consolidatetree */
void rearrange()
{
long i, j, maxinput;
boolean ok;
node *p, *q;
char ch;
printf("Remove everything to the right of which node? ");
inpnum(&i, &ok);
if ( ok == false ) {
/* fall through */
} else if ( i < 1 || i > spp*2 - 1 ) {
/* i is not in range */
ok = false;
} else if (i == root->index ) {
/* i is root */
ok = false;
} else if ( nodep[i-1]->deleted ) {
/* i has been deleted */
ok = false;
} else {
printf("Add at or before which node? ");
inpnum(&j, &ok);
if ( ok == false ) {
/* fall through */
} else if ( j < 1 || j > spp*2 - 1 ) {
/* j is not in range */
ok = false;
} else if ( nodep[j-1]->deleted ) {
/* j has been deleted */
ok = false;
} else if (j != root->index && nodep[nodep[j-1]->back->index - 1]->deleted ) {
/* parent of j has been deleted */
ok = false;
} else if ( nodep[j-1] == nodep[nodep[i-1]->back->index -1] ) {
/* i is j's parent */
ok = false;
} else {
/* make sure that j is not a descendant of i */
for ( p = nodep[j-1]; p != root; p = nodep[p->back->index - 1] ) {
if ( p == nodep[i-1] ) {
ok = false;
break;
}
}
if ( ok ) {
maxinput = 1;
do {
printf("Insert at node (A) or before node (B)? ");
#ifdef WIN32
phyFillScreenColor();
#endif
fflush(stdout);
scanf("%c%*[^\n]", &ch);
getchar();
if (ch == '\n')
ch = ' ';
ch = toupper(ch);
maxinput++;
if (maxinput == 100) {
printf("ERROR: Input failed too many times.\n");
exxit(-1);
}
} while (ch != 'A' && ch != 'B');
if (ch == 'A') {
if ( nodep[j - 1]->deleted || nodep[j - 1]->tip ) {
/* If j is a tip or has been deleted */
ok = false;
} else if ( nodep[j-1] == nodep[nodep[i-1]->back->index -1] ) {
/* If j is i's parent */
ok = false;
} else {
copytree();
re_move(&nodep[i - 1], &q);
add_child(nodep[j - 1], nodep[i - 1]);
if (fromtype == beforenode)
consolidatetree(q->index);
}
} else { /* ch == 'B' */
if (j == root->index) { /* can't insert at root */
ok = false;
} else {
copytree();
printf("Insert before node %ld\n",j);
re_move(&nodep[i - 1], &q);
if (q != NULL) {
nodep[q->index-1]->next->back = nodep[i-1];
nodep[i-1]->back = nodep[q->index-1]->next;
}
add_before(nodep[j - 1], nodep[i - 1]);
}
} /* endif (before or at node) */
} /* endif (ok to do move) */
} /* endif (destination node ok) */
} /* endif (from node ok) */
printree();
if ( !ok )
printf("Not a possible rearrangement. Try again: \n");
else {
written = false;
}
} /* rearrange */
boolean any_deleted(node *p)
{
/* return true if there are any deleted branches from branch on down */
boolean localdl;
localdl = false;
ifdeltrav(p, &localdl);
return localdl;
} /* any_deleted */
void fliptrav(node *p, boolean recurse)
{
node *q, *temp, *r =NULL, *rprev =NULL, *l, *lprev;
boolean lprevflag;
int nodecount, loopcount, i;
if (p->tip)
return;
q = p->next;
l = q;
lprev = p;
nodecount = 0;
do {
nodecount++;
if (q->next->next == p) {
rprev = q;
r = q->next;
}
q = q->next;
} while (p != q);
if (nodecount == 1)
return;
loopcount = nodecount / 2;
for (i=0; inext = r;
rprev->next = l;
temp = r->next;
r->next = l->next;
l->next = temp;
if (i < (loopcount - 1)) {
lprevflag = false;
q = p->next;
do {
if (q == lprev->next && !lprevflag) {
lprev = q;
l = q->next;
lprevflag = true;
}
if (q->next == rprev) {
rprev = q;
r = q->next;
}
q = q->next;
} while (p != q);
}
}
if (recurse) {
q = p->next;
do {
fliptrav(q->back, true);
q = q->next;
} while (p != q);
}
} /* fliptrav */
void flip(long atnode)
{
/* flip at a node left-right */
long i;
boolean ok;
if (atnode == 0) {
printf("Flip branches at which node? ");
inpnum(&i, &ok);
ok = (ok && i > spp && i <= nonodes);
if (ok)
ok = !any_deleted(nodep[i - 1]);
} else {
i = atnode;
ok = true;
}
if (ok) {
copytree();
fliptrav(nodep[i - 1], true);
}
if (atnode == 0)
printree();
if (ok) {
written = false;
return;
}
if ((i >= 1 && i <= spp) ||
(i > spp && i <= nonodes && any_deleted(nodep[i - 1])))
printf("Can't flip there. ");
else
printf("No such node. ");
} /* flip */
void transpose(long atnode)
{
/* flip at a node left-right */
long i;
boolean ok;
if (atnode == 0) {
printf("Transpose branches at which node? ");
inpnum(&i, &ok);
ok = (ok && i > spp && i <= nonodes);
if (ok)
ok = !nodep[i - 1]->deleted;
} else {
i = atnode;
ok = true;
}
if (ok) {
copytree();
fliptrav(nodep[i - 1], false);
}
if (atnode == 0)
printree();
if (ok) {
written = false;
return;
}
if ((i >= 1 && i <= spp) ||
(i > spp && i <= nonodes && nodep[i - 1]->deleted))
printf("Can't transpose there. ");
else
printf("No such node. ");
} /* transpose */
void ifdeltrav(node *p, boolean *localdl)
{
node *q;
if (*localdl)
return;
if (p->tip) {
(*localdl) = ((*localdl) || p->deleted);
return;
}
q = p->next;
do {
(*localdl) = ((*localdl) || q->deleted);
ifdeltrav(q->back, localdl);
q = q->next;
} while (p != q);
} /* ifdeltrav */
double oltrav(node *p)
{
node *q;
double maxlen, templen;
if (p->deleted)
return 0.0;
if (p->tip) {
p->beyond = 0.0;
return 0.0;
} else {
q = p->next;
maxlen = 0;
do {
templen = q->back->deleted ? 0.0 : q->length + oltrav(q->back);
maxlen = (maxlen > templen) ? maxlen : templen;
q->beyond = templen;
q = q->next;
} while (p != q);
p->beyond = maxlen;
return (maxlen);
}
} /* oltrav */
void outlength()
{
/* compute the farthest combined length out from each node */
oltrav(root);
} /* outlength */
void midpoint()
{
/* midpoint root the tree */
double balance, greatlen, lesslen, grlen, maxlen;
node *maxnode, *grnode, *lsnode =NULL;
boolean ok = true;
boolean changed = false;
node *p, *q;
long nodecount = 0;
boolean multi = false;
copytree();
p = root;
outlength();
q = p->next;
greatlen = 0;
grnode = q->back;
lesslen = 0;
q = root->next;
do {
p = q;
nodecount++;
q = p->next;
} while (q != root);
if (nodecount > 2)
multi = true;
/* Find the two greatest lengths reaching from root to tips.
Also find the lengths and node pointers of the first nodes in the
direction of those two greatest lengths. */
p = root;
q = root->next;
do {
if (greatlen <= q->beyond) {
lesslen = greatlen;
lsnode = grnode;
greatlen = q->beyond;
grnode = q->back;
}
if ((greatlen > q->beyond) && (q->beyond >= lesslen)) {
lesslen = q->beyond;
lsnode = q->back;
}
q = q->next;
} while (p != q);
/* If we don't have two non-deleted nodes to balance between then
we can't midpoint root the tree */
if (grnode->deleted || lsnode->deleted || grnode == lsnode)
ok = false;
balance = greatlen - (greatlen + lesslen) / 2.0;
grlen = grnode->length;
while ((balance - grlen > 1e-10) && ok) {
/* First, find the most distant immediate child of grnode
and reroot to it. */
p = grnode;
q = p->next;
maxlen = 0;
maxnode = q->back;
do {
if (maxlen <= q->beyond) {
maxlen = q->beyond;
maxnode = q->back;
}
q = q->next;
} while (p != q);
reroot(maxnode);
changed = true;
/* Reassess the situation, using the same "find the two greatest
lengths" code as occurs before the while loop. If another reroot
is necessary, this while loop will repeat. */
p = root;
outlength();
q = p->next;
greatlen = 0;
grnode = q->back;
lesslen = 0;
do {
if (greatlen <= q->beyond) {
lesslen = greatlen;
lsnode = grnode;
greatlen = q->beyond;
grnode = q->back;
}
if ((greatlen > q->beyond) && (q->beyond >= lesslen)) {
lesslen = q->beyond;
lsnode = q->back;
}
q = q->next;
} while (p != q);
if (grnode->deleted || lsnode->deleted || grnode == lsnode)
ok = false;
balance = greatlen - (greatlen + lesslen) / 2.0;
grlen = grnode->length;
}; /* end of while ((balance > grlen) && ok) */
if (ok) {
/*xx the following ignores deleted nodes */
/* this may be ok because deleted nodes are omitted from length calculations */
if (multi) {
reroot(grnode); /*xx need length corrections */
p = root;
outlength();
q = p->next;
greatlen = 0;
grnode = q->back;
lesslen = 0;
do {
if (greatlen <= q->beyond) {
lesslen = greatlen;
lsnode = grnode;
greatlen = q->beyond;
grnode = q->back;
}
if ((greatlen > q->beyond) && (q->beyond >= lesslen)) {
lesslen = q->beyond;
lsnode = q->back;
}
q = q->next;
} while (p != q);
balance = greatlen - (greatlen + lesslen) / 2.0;
}
grnode->length -= balance;
if (((grnode->length) < 0.0) && (grnode->length > -1.0e-10))
grnode->length = 0.0;
grnode->back->length = grnode->length;
lsnode->length += balance;
if (((lsnode->length) < 0.0) && (lsnode->length > -1.0e-10))
lsnode->length = 0.0;
lsnode->back->length = lsnode->length;
}
printree();
if (ok) {
if (any_deleted(root))
printf("Deleted nodes were not used in midpoint calculations.\n");
}
else {
printf("Can't perform midpoint because of deleted branches.\n");
if (changed) {
undo();
printf("Tree restored to original state. Undo information lost.\n");
}
}
} /* midpoint */
void deltrav(node *p, boolean value)
{
/* register p and p's children as deleted or extant, depending on value */
node *q;
p->deleted = value;
if (p->tip)
return;
q = p->next;
do {
deltrav(q->back, value);
q = q->next;
} while (p != q);
} /* deltrav */
void fill_del(node*p)
{
int alldell;
node *q = p;
if ( p->next == NULL) return;
q=p->next;
while ( q != p) {
fill_del(q->back);
q=q->next;
}
alldell = 1;
q=p->next;
while ( q != p) {
if ( !q->back->deleted ) {
alldell = 0;
}
q=q->next;
}
p->deleted = alldell;
}
void reg_del(node *delp, boolean value)
{
/* register delp and all of delp's children as deleted */
deltrav(delp, value);
} /* reg_del */
boolean isdeleted(long nodenum)
{
/* true if nodenum is a node number in a deleted branch */
return(nodep[nodenum - 1]->deleted);
} /* isdeleted */
void deletebranch()
{
/* delete a node */
long i;
boolean ok1;
printf("Delete everything to the right of which node? ");
inpnum(&i, &ok1);
ok1 = (ok1 && i >= 1 && i <= nonodes && i != root->index && !isdeleted(i));
if (ok1) {
copytree();
reg_del(nodep[i - 1],true);
}
printree();
if (!ok1)
printf("Not a possible deletion. Try again.\n");
else {
written = false;
}
} /* deletebranch */
void restorebranch()
{
/* restore deleted branches */
long i;
boolean ok1;
printf("Restore everything to the right of which node? ");
inpnum(&i, &ok1);
ok1 = (ok1 && i >= 1 && i < spp * 2 && i != root->index && isdeleted(i)
&& !nodep[nodep[i - 1]->back->index - 1]->deleted);
if (ok1) {
reg_del(nodep[i - 1],false);
}
printree();
if (!ok1)
printf("Not a possible restoration. Try again: \n");
else {
written = false;
}
} /* restorebranch */
void del_or_restore()
{
/* delete or restore a branch */
long maxinput;
Char ch;
if (any_deleted(root)) {
maxinput = 1;
do {
printf("Enter D to delete a branch\n");
printf("OR enter R to restore a branch: ");
#ifdef WIN32
phyFillScreenColor();
#endif
fflush(stdout);
scanf("%c%*[^\n]", &ch);
getchar();
if (ch == '\n')
ch = ' ';
ch = (isupper((int)ch)) ? ch : toupper((int)ch);
maxinput++;
if (maxinput == 100) {
printf("ERROR: too many tries at choosing option\n");
embExitBad();
}
} while (ch != 'D' && ch != 'R');
if (ch == 'R')
restorebranch();
else
deletebranch();
}
else
deletebranch();
} /* del_or_restore */
void undo()
{
/* don't undo to an uninitialized tree */
if (!treesets[othertree].initialized) {
printree();
printf("Nothing to undo.\n");
return;
}
treesets[whichtree].root = root;
treesets[whichtree].nodep = nodep;
treesets[whichtree].nonodes = nonodes;
treesets[whichtree].waswritten = waswritten;
treesets[whichtree].hasmult = hasmult;
treesets[whichtree].haslengths = haslengths;
treesets[whichtree].nolengths = nolengths;
treesets[whichtree].initialized = true;
whichtree = othertree;
root = treesets[whichtree].root;
nodep = treesets[whichtree].nodep;
nonodes = treesets[whichtree].nonodes;
waswritten = treesets[whichtree].waswritten;
hasmult = treesets[whichtree].hasmult;
haslengths = treesets[whichtree].haslengths;
nolengths = treesets[whichtree].nolengths;
if (othertree == 0)
othertree = 1;
else
othertree = 0;
printree();
} /* undo */
/*
These attributes of nodes in the tree are modified by treetrav()
in preparation for writing a tree to disk.
boolean deadend This node is not deleted but all of its children
are, so this node will be treated as such when
the tree is written or displayed.
boolean onebranch This node has only one valid child, so that this
node will not be written and its child will be
written as a child of its grandparent with the
appropriate summing of lengths.
nodep *onebranchnode
Used if onebranch is true. Onebranchnode points
to the one valid child. This child may be one or
more generations down from the current node.
double onebranchlength
Used if onebranch is true. Onebranchlength is
the length from the current node to the valid
child.
*/
void treetrav(node *p)
{
long branchcount = 0;
node *q, *onebranchp =NULL;
/* Count the non-deleted branches hanging off of this node into branchcount.
If there is only one such branch, onebranchp points to that branch. */
if (p->tip)
return;
q = p->next;
do {
if (!q->back->deleted) {
if (!q->back->tip)
treetrav(q->back);
if (!q->back->deadend && !q->back->deleted) {
branchcount++;
onebranchp = q->back;
}
}
q = q->next;
} while (p != q);
if (branchcount == 0)
p->deadend = true;
else
p->deadend = false;
p->onebranch = false;
if (branchcount == 1 && onebranchp->tip) {
p->onebranch = true;
p->onebranchnode = onebranchp;
p->onebranchhaslength = (p->haslength || (p == root))
&& onebranchp->haslength;
if (p->onebranchhaslength)
p->onebranchlength = onebranchp->length + p->length;
}
if (branchcount == 1 && !onebranchp->tip) {
p->onebranch = true;
if (onebranchp->onebranch) {
p->onebranchnode = onebranchp->onebranchnode;
p->onebranchhaslength = (p->haslength || (p == root))
&& onebranchp->onebranchhaslength;
if (p->onebranchhaslength)
p->onebranchlength = onebranchp->onebranchlength + p->length;
} else {
p->onebranchnode = onebranchp;
p->onebranchhaslength = p->haslength && onebranchp->haslength;
if (p->onebranchhaslength)
p->onebranchlength = onebranchp->length + p->length;
}
}
} /* treetrav */
void simcopynode(node *fromnode, node *tonode)
{
/* Copy the contents of a node from fromnode to tonode. */
int i;
tonode->index = fromnode->index;
tonode->deleted = fromnode->deleted;
tonode->tip = fromnode->tip;
tonode->hasname = fromnode->hasname;
if (fromnode->hasname)
for (i=0;inayme[i] = fromnode->nayme[i];
tonode->haslength = fromnode->haslength;
if (fromnode->haslength)
tonode->length = fromnode->length;
} /* simcopynode */
node *simcopytrav(node *p)
{
/* Traverse the tree from p on down, copying nodes to the other tree */
node *q, *newnode, *newnextnode, *temp;
long lastnodeidx = 0;
gnu(&grbg, &newnode);
simcopynode(p, newnode);
if (nodep[p->index - 1] == p)
simplifiedtree.nodep[p->index - 1] = newnode;
/* if this is a tip, return now */
if (p->tip)
return newnode;
if (p->onebranch && p->onebranchnode->tip) {
simcopynode(p->onebranchnode, newnode);
if (p->onebranchhaslength)
newnode->length = p->onebranchlength;
return newnode;
} else if (p->onebranch && !p->onebranchnode->tip) {
/* recurse down p->onebranchnode */
p->onebranchnode->length = p->onebranchlength;
p->onebranchnode->haslength = p->onebranchnode->haslength;
return simcopytrav(p->onebranchnode);
} else {
/* Multiple non-deleted branch case: go round the node recursing
down the branches. Don't go down deleted branches or dead ends. */
q = p->next;
while (q != p) {
if (!q->back->deleted && !q->back->deadend)
lastnodeidx = q->back->index;
q = q->next;
}
q = p->next;
gnu(&grbg, &newnextnode);
simcopynode(q, newnextnode);
newnode->next = newnextnode;
do {
/* If branch is deleted or is a dead end, do not recurse
down the branch. */
if (!q->back->deleted && !q->back->deadend) {
newnextnode->back = simcopytrav(q->back);
newnextnode->back->back = newnextnode;
q = q->next;
if (newnextnode->back->index == lastnodeidx) {
newnextnode->next = newnode;
break;
}
if (q == p) {
newnextnode->next = newnode;
} else {
temp = newnextnode;
gnu(&grbg, &newnextnode);
simcopynode(q, newnextnode);
temp->next = newnextnode;
}
} else { /*xx this else and q=q->next are experimental
(seems to be working) */
q = q->next;
}
} while (q != p);
}
return newnode;
} /* simcopytrav */
void simcopytree()
{
/* Make a simplified copy of the current tree for rooting/unrooting
on output. Deleted notes are removed and lengths are consolidated. */
simplifiedtree.root = simcopytrav(root);
/*xx If there are deleted nodes, nonodes will be different.
However, nonodes is not used in the simplified tree. */
simplifiedtree.nonodes = nonodes;
simplifiedtree.waswritten = waswritten;
simplifiedtree.hasmult = hasmult;
simplifiedtree.haslengths = haslengths;
simplifiedtree.nolengths = nolengths;
simplifiedtree.initialized = true;
} /* simcopytree */
void writebranchlength(double x)
{
long w;
/* write branch length onto output file, keeping track of what
column of line you are in, and writing to correct precision */
if (x > 0.0)
w = (long)(0.43429448222 * log(x));
else if (x == 0.0)
w = 0;
else
w = (long)(0.43429448222 * log(-x)) + 1;
if (w < 0)
w = 0;
if ((long)(100000*x) == 100000*(long)x) {
if (!xmltree)
putc(':', outtree);
fprintf(outtree, "%*.1f", (int)(w + 2), x);
col += w + 3;
}
else {
if ((long)(100000*x) == 10000*(long)(10*x)) {
if (!xmltree)
putc(':', outtree);
fprintf(outtree, "%*.1f", (int)(w + 3), x);
col += w + 4;
}
else {
if ((long)(100000*x) == 1000*(long)(100*x)) {
if (!xmltree)
putc(':', outtree);
fprintf(outtree, "%*.2f", (int)(w + 4), x);
col += w + 5;
}
else {
if ((long)(100000*x) == 100*(long)(1000*x)) {
if (!xmltree)
putc(':', outtree);
fprintf(outtree, "%*.3f", (int)(w + 5), x);
col += w + 6;
}
else {
if ((long)(100000*x) == 10*(long)(10000*x)) {
if (!xmltree)
putc(':', outtree);
fprintf(outtree, "%*.4f", (int)(w + 6), x);
col += w + 7;
}
else {
if (!xmltree)
putc(':', outtree);
fprintf(outtree, "%*.5f", (int)(w + 7), x);
col += w + 8;
}
}
}
}
}
} /* writebranchlength */
void treeout(node *p, boolean writeparens, double addlength, long indent)
{
/* write out file with representation of final tree */
long i, n, lastnodeidx = 0;
Char c;
double x;
boolean comma;
node *q;
/* If this is a tip or there are no non-deleted branches from this node,
render this node as a tip (write its name). */
if (p == root) {
if (xmltree)
indent = 0;
else
indent = 0;
if (xmltree) {
fprintf(outtree, ""); /* assumes no length at root! */
} else putc('(', outtree);
}
if (p->tip) {
if (p->hasname) {
n = 0;
for (i = 1; i <= MAXNCH; i++) {
if ((nodep[p->index - 1]->nayme[i - 1] != '\0')
&& (nodep[p->index - 1]->nayme[i - 1] != ' '))
n = i;
}
indent += 2;
if (xmltree) {
putc('\n', outtree);
for (i = 1; i <= indent; i++)
putc(' ', outtree);
fprintf(outtree, "haslength) {
fprintf(outtree, " length=");
x = p->length;
writebranchlength(x);
}
putc('>', outtree);
fprintf(outtree, "");
}
for (i = 0; i < n; i++) {
c = nodep[p->index - 1]->nayme[i];
if (c == ' ')
c = '_';
putc(c, outtree);
}
col += n;
if (xmltree)
fprintf(outtree, "");
}
} else if (p->onebranch && p->onebranchnode->tip) {
if (p->onebranchnode->hasname) {
n = 0;
for (i = 1; i <= MAXNCH; i++) {
if ((nodep[p->index - 1]->nayme[i - 1] != '\0')
&& (nodep[p->index - 1]->nayme[i - 1] != ' '))
n = i;
indent += 2;
if (xmltree) {
putc('\n', outtree);
for (i = 1; i <= indent; i++)
putc(' ', outtree);
fprintf(outtree, "haslength && writeparens) || p->onebranch) {
if (!(p->onebranch && !p->onebranchhaslength)) {
fprintf(outtree, " length=");
if (p->onebranch)
x = p->onebranchlength;
else
x = p->length;
x += addlength;
writebranchlength(x);
}
fprintf(outtree, "");
}
}
for (i = 0; i < n; i++) {
c = p->onebranchnode->nayme[i];
if (c == '_')
c = ' ';
putc(c, outtree);
}
col += n;
if (xmltree)
fprintf(outtree, "");
}
}
} else if (p->onebranch && !p->onebranchnode->tip) {
treeout(p->onebranchnode, true, 0.0, indent);
} else {
/* Multiple non-deleted branch case: go round the node
recursing down the branches. */
if (xmltree) {
putc('\n', outtree);
indent += 2;
for (i = 1; i <= indent; i++)
putc(' ', outtree);
if (p == root)
fprintf(outtree, "");
}
if (p != root) {
if (xmltree) {
fprintf(outtree, "haslength && writeparens) || p->onebranch) {
if (!(p->onebranch && !p->onebranchhaslength)) {
fprintf(outtree, " length=\"");
if (p->onebranch)
x = p->onebranchlength;
else
x = p->length;
x += addlength;
writebranchlength(x);
}
fprintf(outtree, "\">");
}
else fprintf(outtree, ">");
} else putc('(', outtree);
}
(col)++;
q = p->next;
while (q != p) {
if (!q->back->deleted && !q->back->deadend)
lastnodeidx = q->back->index;
q = q->next;
}
q = p->next;
while (q != p) {
comma = true;
/* If branch is deleted or is a dead end, do not recurse
down the branch and do not write a comma afterwards.
*/
if (!q->back->deleted && !q->back->deadend)
treeout(q->back, true, 0.0, indent);
else
comma = false;
if (q->back->index == lastnodeidx)
comma = false;
q = q->next;
if (q == p)
break;
if ((q->next == p) && (q->back->deleted || q->back->deadend))
break;
if (comma && !xmltree)
putc(',', outtree);
(col)++;
if ((!xmltree) && col > 65) {
putc('\n', outtree);
col = 0;
}
}
/* The right paren ')' closes off this level of recursion. */
if (p != root) {
if (xmltree) {
fprintf(outtree, "\n");
for (i = 1; i <= indent; i++)
putc(' ', outtree);
}
if (xmltree) {
fprintf(outtree, "");
} else putc(')', outtree);
}
(col)++;
}
if (!xmltree)
if ((p->haslength && writeparens) || p->onebranch) {
if (!(p->onebranch && !p->onebranchhaslength)) {
if (p->onebranch)
x = p->onebranchlength;
else
x = p->length;
x += addlength;
writebranchlength(x);
}
}
if (p == root) {
if (xmltree) {
fprintf(outtree, "\n \n\n");
} else putc(')', outtree);
}
} /* treeout */
void maketemptriad(node **p, long index)
{
/* Initiate an internal node with stubs for two children */
long i, j;
node *q;
q = NULL;
for (i = 1; i <= 3; i++) {
gnu(&grbg, p);
(*p)->index = index;
(*p)->hasname = false;
(*p)->haslength = false;
(*p)->deleted=false;
(*p)->deadend=false;
(*p)->onebranch=false;
(*p)->onebranchhaslength=false;
for (j=0;jnayme[j] = '\0';
(*p)->next = q;
q = *p;
}
(*p)->next->next->next = *p;
q = (*p)->next;
while (*p != q) {
(*p)->back = NULL;
(*p)->tip = false;
*p = (*p)->next;
}
} /* maketemptriad */
void roottreeout(boolean *userwantsrooted)
{
/* write out file with representation of final tree */
long trnum, trnumwide;
boolean treeisrooted = false;
treetrav(root);
simcopytree(); /* Prepare a copy of the going tree without deleted branches */
treesets[whichtree].root = root; /* Store the current root */
if (nexus) {
trnum = treenumber;
trnumwide = 1;
while (trnum >= 10) {
trnum /= 10;
trnumwide++;
}
fprintf(outtree, "TREE PHYLIP_%*ld = ", (int)trnumwide, treenumber);
if (!(*userwantsrooted))
fprintf(outtree, "[&U] ");
else
fprintf(outtree, "[&R] ");
col += 15;
}
root = simplifiedtree.root; /* Point root at simplified tree */
root->haslength = false; /* Root should not have a length */
if (root->tip)
treeisrooted = true;
else {
if (root->next->next->next == root)
treeisrooted = true;
else
treeisrooted = false;
}
if (*userwantsrooted && !treeisrooted)
notrootedtorooted();
if (!(*userwantsrooted) && treeisrooted)
rootedtonotrooted();
if ((*userwantsrooted && treeisrooted) ||
(!(*userwantsrooted) && !treeisrooted)) {
treeout(root,true,0.0, 0);
}
root = treesets[whichtree].root; /* Point root at original (real) tree */
if (!xmltree) {
if (hasmult)
fprintf(outtree, "[%6.4f];\n", trweight);
else
fprintf(outtree, ";\n");
}
} /* roottreeout */
void notrootedtorooted()
{
node *newbase, *temp;
/* root halfway along leftmost branch of unrooted tree */
/* create a new triad for the new base */
maketemptriad(&newbase,nonodes+1);
/* Take left branch and make it the left branch of newbase */
newbase->next->back = root->next->back;
newbase->next->next->back = root;
/* If needed, divide length between left and right branches */
if (newbase->next->back->haslength) {
newbase->next->back->length /= 2.0;
newbase->next->next->back->length =
newbase->next->back->length;
newbase->next->next->back->haslength = true;
}
/* remove leftmost ring node from old base ring */
temp = root->next->next;
chuck(&grbg, root->next);
root->next = temp;
/* point root at new base and write the tree */
root = newbase;
treeout(root,true,0.0, 0);
/* (since tree mods are to simplified tree and will not be used
for general purpose tree editing, much initialization can be
skipped.) */
} /* notrootedtorooted */
void rootedtonotrooted()
{
node *q, *r, *temp, *newbase;
boolean sumhaslength = false;
double sumlength = 0;
/* Use the leftmost non-tip immediate descendant of the root,
root at that, write a multifurcation with that as the base.
If both descendants are tips, write tree as is. */
root = simplifiedtree.root;
/* first, search for leftmost non-tip immediate descendent of root */
q = root->next->back;
r = root->next->next->back;
if (q->tip && r->tip) {
treeout(root,true,0.0, 0);
} else if (!(q->tip)) {
/* allocate new base pointer */
gnu(&grbg,&newbase);
newbase->next = q->next;
q->next = newbase;
q->back = r;
r->back = q;
if (q->haslength && r->haslength) {
sumlength = q->length + r->length;
sumhaslength = true;
}
if (sumhaslength) {
q->length = sumlength;
q->back->length = sumlength;
} else {
q->haslength = false;
r->haslength = false;
}
chuck(&grbg, root->next->next);
chuck(&grbg, root->next);
chuck(&grbg, root);
root = newbase;
treeout(root, true, 0.0, 0);
} else if (q-tip && !(r->tip)) {
temp = r;
do {
temp = temp->next;
} while (temp->next != r);
gnu(&grbg,&newbase);
newbase->next = temp->next;
temp->next = newbase;
q->back = r;
r->back = q;
if (q->haslength && r->haslength) {
sumlength = q->length + r->length;
sumhaslength = true;
}
if (sumhaslength) {
q->length = sumlength;
q->back->length = sumlength;
} else {
q->haslength = false;
r->haslength = false;
}
chuck(&grbg, root->next->next);
chuck(&grbg, root->next);
chuck(&grbg, root);
root = newbase;
treeout(root, true, 0.0, 0);
}
} /* rootedtonotrooted */
void treewrite(boolean *done)
{
/* write out tree to a file */
long maxinput;
boolean rooted;
if (nexus && onfirsttree) {
fprintf(outtree, "#NEXUS\n");
fprintf(outtree, "BEGIN TREES\n");
fprintf(outtree, "TRANSLATE;\n"); /* MacClade needs this */
}
if (xmltree && onfirsttree) {
fprintf(outtree, "\n");
}
onfirsttree = false;
maxinput = 1;
do {
fprintf(stderr, "Enter R if the tree is to be rooted, ");
fprintf(stderr, "OR enter U if the tree is to be unrooted: ");
#ifdef WIN32
phyFillScreenColor();
#endif
fflush(stdout);
scanf("%c%*[^\n]", &ch);
getchar();
if (ch == '\n')
ch = ' ';
ch = (isupper((int)ch)) ? ch : toupper((int)ch);
maxinput++;
if (maxinput == 100) {
fprintf(stderr, "ERROR: too many tries at choosing option\n");
embExitBad();
}
} while (ch != 'R' && ch != 'U');
col = 0;
rooted = (ch == 'R');
roottreeout(&rooted);
treenumber++;
fprintf(stderr, "\nTree written to file \"%s\"\n\n", outtreename);
waswritten = true;
written = true;
if (!(*done))
printree();
FClose(outtree);
} /* treewrite */
void retree_window(adjwindow action)
{
/* move viewing window of tree */
switch (action) {
case left:
if (leftedge != 1)
leftedge -= hscroll;
break;
case downn:
/* The 'topedge + 3' is needed to allow downward scrolling
when part of the tree is above the screen and only 1 or 2 lines
are below it. */
if (treelines - topedge + 3 >= screenlines)
topedge += vscroll;
break;
case upp:
if (topedge != 1)
topedge -= vscroll;
break;
case right:
if (leftedge < vscreenwidth+2)
{
if (hscroll > leftedge - vscreenwidth + 1)
leftedge = vscreenwidth;
else
leftedge += hscroll;
}
break;
}
printree();
} /* retree_window */
void getlength(double *length, reslttype *reslt, boolean *hslngth)
{
long maxinput;
double valyew;
char tmp[100];
valyew = 0.0;
maxinput = 1;
do {
printf("\nEnter the new branch length\n");
printf("OR enter U to leave the length unchanged\n");
if (*hslngth)
printf("OR enter R to remove the length from this branch: \n");
getstryng(tmp);
if (tmp[0] == 'u' || tmp[0] == 'U'){
*reslt = quit;
break;
}
else if (tmp[0] == 'r' || tmp[0] == 'R') {
(*reslt) = remoov;
break;}
else if (sscanf(tmp,"%lf",&valyew) == 1){
(*reslt) = valid;
break;
}
maxinput++;
if (maxinput == 100) {
printf("ERROR: too many tries at choosing option\n");
embExitBad();
}
} while (1);
(*length) = valyew;
} /* getlength */
void changelength()
{
/* change or specify the length of a tip */
boolean hslngth;
boolean ok;
long i, w, maxinput;
double length, x;
Char ch;
reslttype reslt;
node *p;
maxinput = 1;
do {
printf("Specify length of which branch (0 = all branches)? ");
inpnum(&i, &ok);
ok = (ok && (unsigned long)i <= nonodes);
if (ok && (i != 0))
ok = (ok && !nodep[i - 1]->deleted);
if (i == 0)
ok = (nodep[i - 1] != root);
maxinput++;
if (maxinput == 100) {
printf("ERROR: too many tries at choosing option\n");
embExitBad();
}
} while (!ok);
if (i != 0) {
p = nodep[i - 1];
putchar('\n');
if (p->haslength) {
x = p->length;
if (x > 0.0)
w = (long)(0.43429448222 * log(x));
else if (x == 0.0)
w = 0;
else
w = (long)(0.43429448222 * log(-x)) + 1;
if (w < 0)
w = 0;
printf("The current length of this branch is %*.5f\n", (int)(w + 7), x);
} else
printf("This branch does not have a length\n");
hslngth = p->haslength;
getlength(&length, &reslt, &hslngth);
switch (reslt) {
case valid:
copytree();
p->length = length;
p->haslength = true;
if (p->back != NULL) {
p->back->length = length;
p->back->haslength = true;
}
break;
case remoov:
copytree();
p->haslength = false;
if (p->back != NULL)
p->back->haslength = false;
break;
case quit:
/* blank case */
break;
}
} else {
printf("\n (this operation cannot be undone)\n");
maxinput = 1;
do {
printf("\n enter U to leave the lengths unchanged\n");
printf("OR enter R to remove the lengths from all branches: \n");
#ifdef WIN32
phyFillScreenColor();
#endif
fflush(stdout);
scanf("%c%*[^\n]", &ch);
getchar();
if (ch == '\n')
ch = ' ';
maxinput++;
if (maxinput == 100) {
printf("ERROR: too many tries at choosing option\n");
exxit(-1);
}
} while (ch != 'U' && ch != 'u' && ch != 'R' && ch != 'r');
if (ch == 'R' || ch == 'r') {
copytree();
for (i = 0; i < spp; i++)
nodep[i]->haslength = false;
for (i = spp; i < nonodes; i++) {
if (nodep[i] != NULL) {
nodep[i]->haslength = false;
nodep[i]->next->haslength = false;
nodep[i]->next->next->haslength = false;
}
}
}
}
printree();
} /* changelength */
void changename()
{
/* change or specify the name of a tip */
boolean ok;
long i, n, tipno;
char tipname[100];
for(;;) {
for(;;) {
printf("Specify name of which tip? (enter its number or 0 to quit): ");
inpnum(&i, &ok);
if (i > 0 && ((unsigned long)i <= spp) && ok)
if (!nodep[i - 1]->deleted) {
tipno = i;
break;
}
if (i == 0) {
tipno = 0;
break;
}
}
if (tipno == 0)
break;
if (nodep[tipno - 1]->hasname) {
n = 0;
/* this is valid because names are padded out to MAXNCH with nulls */
for (i = 1; i <= MAXNCH; i++) {
if (nodep[tipno - 1]->nayme[i - 1] != '\0')
n = i;
}
printf("The current name of tip %ld is \"", tipno);
for (i = 0; i < n; i++)
putchar(nodep[tipno - 1]->nayme[i]);
printf("\"\n");
}
copytree();
for (i = 0; i < MAXNCH; i++)
nodep[tipno - 1]->nayme[i] = ' ';
printf("Enter new tip name: ");
i = 1;
getstryng(tipname);
strncpy(nodep[tipno-1]->nayme,tipname,MAXNCH);
nodep[tipno - 1]->hasname = true;
printree();
}
printree();
} /* changename */
void clade()
{
/* pick a subtree and show only that on screen */
long i;
boolean ok;
printf("Select subtree rooted at which node (0 for whole tree)? ");
inpnum(&i, &ok);
ok = (ok && (unsigned long)i <= nonodes);
if (ok) {
subtree = (i > 0);
if (subtree)
nuroot = nodep[i - 1];
else
nuroot = root;
}
printree();
if (!ok)
printf("Not possible to use this node. ");
} /* clade */
void changeoutgroup()
{
long i, maxinput;
boolean ok;
maxinput = 1;
do {
printf("Which node should be the new outgroup? ");
inpnum(&i, &ok);
ok = (ok && i >= 1 && i <= nonodes && i != root->index);
if (ok)
ok = (ok && !nodep[i - 1]->deleted);
if (ok)
ok = !nodep[nodep[i - 1]->back->index - 1]->deleted;
if (ok)
outgrno = i;
maxinput++;
if (maxinput == 100) {
printf("ERROR: too many tries at choosing option\n");
embExitBad();
}
} while (!ok);
copytree();
reroot(nodep[outgrno - 1]);
printree();
written = false;
} /* changeoutgroup */
void redisplay()
{
long maxinput;
boolean done;
char ch;
done = false;
maxinput = 1;
do {
fprintf(stderr, "NEXT? (R . ");
if (haslengths)
fprintf(stderr, "= ");
fprintf(stderr, "U W O ");
if (haslengths)
fprintf(stderr, "M ");
fprintf(stderr, "T F D B N H J K L C + ? X Q) (? for Help): ");
#ifdef WIN32
phyFillScreenColor();
#endif
fflush(stdout);
scanf("%c%*[^\n]", &ch);
getchar();
if (ch == '\n')
ch = ' ';
ch = isupper((int)ch) ? ch : toupper((int)ch);
if (ch == 'C' || ch == 'F' || ch == 'O' || ch == 'R' ||
ch == 'U' || ch == 'X' || ch == 'Q' || ch == '.' ||
ch == 'W' || ch == 'B' || ch == 'N' || ch == '?' ||
ch == 'H' || ch == 'J' || ch == 'K' || ch == 'L' ||
ch == '+' || ch == 'T' || ch == 'D' ||
(haslengths && ch == 'M') ||
(haslengths && ch == '=')) {
switch (ch) {
case 'R':
rearrange();
break;
case '.':
printree();
break;
case '=':
togglelengths();
break;
case 'U':
undo();
break;
case 'W':
treewrite(&done);
break;
case 'O':
changeoutgroup();
break;
case 'M':
midpoint();
break;
case 'T':
transpose(0);
break;
case 'F':
flip(0);
break;
case 'C':
clade();
break;
case 'D':
del_or_restore();
break;
case 'B':
changelength();
break;
case 'N':
changename();
break;
case 'H':
retree_window(left);
break;
case 'J':
retree_window(downn);
break;
case 'K':
retree_window(upp);
break;
case 'L':
retree_window(right);
break;
case '?':
retree_help();
break;
case '+':
if (treesread \n");
else if (nexus)
fprintf(outtree, "END;\n");
}
FClose(intree);
FClose(outtree);
#ifdef MAC
fixmacfile(outtreename);
#endif
#ifdef WIN32
phyRestoreConsoleAttributes();
#endif
embExit();
return 0;
} /* Retree */
PHYLIPNEW-3.69.650/src/discboot.c 0000664 0001750 0001750 00000070013 11616234203 013026 0000000 0000000 #include "phylip.h"
#include "seq.h"
/* version 3.6. (c) Copyright 1993-2004 by the University of Washington.
Written by Joseph Felsenstein, Akiko Fuseki, Sean Lamont, Andrew Keeffe,
and Doug Buxton.
Permission is granted to copy and use this program provided no fee is
charged for it and provided that this copyright notice is not removed. */
typedef enum {
seqs, morphology, restsites, genefreqs
} datatype;
typedef enum {
dna, rna, protein
} seqtype;
AjPPhyloState* phylostate = NULL;
AjPPhyloProp phyloweights = NULL;
AjPPhyloProp phyloanc = NULL;
AjPPhyloProp phylomix = NULL;
AjPPhyloProp phylofact = NULL;
#ifndef OLDC
/* function prototypes */
//void getoptions(void);
void emboss_getoptions(char *pgm, int argc, char *argv[]);
void seqboot_inputnumbersstate(AjPPhyloState);
void inputoptions(void);
void seqboot_inputdatastate(AjPPhyloState);
void allocrest(void);
void allocnew(void);
void doinput(int argc, Char *argv[]);
void bootweights(void);
void sppermute(long);
void charpermute(long, long);
void writedata(void);
void writeweights(void);
void writecategories(void);
void writeauxdata(steptr, FILE*);
void writefactors(void);
void bootwrite(void);
void seqboot_inputaux(steptr, FILE*);
void seqboot_inputfactors(AjPPhyloProp fact);
/* function prototypes */
#endif
FILE *outcatfile, *outweightfile, *outmixfile, *outancfile, *outfactfile;
Char infilename[FNMLNGTH], catfilename[FNMLNGTH], weightfilename[FNMLNGTH], mixfilename[FNMLNGTH], ancfilename[FNMLNGTH], factfilename[FNMLNGTH];
const char* outfilename;
AjPFile embossoutfile;
const char* outweightfilename;
AjPFile embossoutweightfile;
const char* outmixfilename;
AjPFile embossoutmixfile;
const char* outancfilename;
AjPFile embossoutancfile;
const char* outcatfilename;
AjPFile embossoutcatfile;
const char* outfactfilename;
AjPFile embossoutfactfile;
long sites, loci, maxalleles, groups, newsites, newersites,
newgroups, newergroups, nenzymes, reps, ws, blocksize, categs, maxnewsites;
boolean bootstrap, permute, ild, lockhart, jackknife, regular, xml, nexus,
weights, categories, factors, enzymes, all, justwts, progress, mixture,
firstrep, ancvar;
double fracsample;
datatype data;
seqtype seq;
steptr oldweight, where, how_many, newwhere, newhowmany,
newerwhere, newerhowmany, factorr, newerfactor, mixdata, ancdata;
steptr *charorder;
Char *factor;
long *alleles;
Char **nodep;
double **nodef;
long **sppord;
longer seed;
void emboss_getoptions(char *pgm, int argc, char *argv[])
{
AjPStr test = NULL;
AjPStr typeofseq = NULL;
AjPStr justweights = NULL;
AjBool rewrite = false;
long inseed, inseed0;
data = morphology;
seq = dna;
bootstrap = false;
jackknife = false;
permute = false;
ild = false;
lockhart = false;
blocksize = 1;
regular = true;
fracsample = 1.0;
all = false;
reps = 100;
weights = false;
mixture = false;
ancvar = false;
categories = false;
justwts = false;
printdata = false;
dotdiff = true;
progress = true;
interleaved = true;
xml = false;
nexus = false;
factors = false;
enzymes = false;
embInitPV(pgm, argc, argv, "PHYLIPNEW",VERSION);
phylostate = ajAcdGetDiscretestates("infile");
phylofact = ajAcdGetProperties("factorfile");
if(phylofact) {
factors = true;
embossoutfactfile = ajAcdGetOutfile("outfactfile");
emboss_openfile(embossoutfactfile, &outfactfile, &outfactfilename);
}
test = ajAcdGetListSingle("test");
if(ajStrMatchC(test, "b")) {
bootstrap = true;
regular = ajAcdGetToggle("regular");
if(regular) fracsample = 1.0;
else {
fracsample = ajAcdGetFloat("fracsample");
fracsample = fracsample/100.0;
}
blocksize = ajAcdGetInt("blocksize");
}
else if(ajStrMatchC(test, "j")) {
jackknife = true;
regular = ajAcdGetToggle("regular");
if(regular) fracsample = 0.5;
else {
fracsample = ajAcdGetFloat("fracsample");
fracsample = fracsample/100.0;
}
}
else if(ajStrMatchC(test, "c")) permute = true;
else if(ajStrMatchC(test, "o")) ild = true;
else if(ajStrMatchC(test, "s")) lockhart = true;
else if(ajStrMatchC(test, "r")) rewrite = true;
if(rewrite) {
if (data == morphology) {
typeofseq = ajAcdGetListSingle("morphseqtype");
if(ajStrMatchC(typeofseq, "d")) seq = dna;
else if(ajStrMatchC(typeofseq, "r")) seq = rna;
else if(ajStrMatchC(typeofseq, "p")) seq = protein;
}
}
else{
reps = ajAcdGetInt("reps");
inseed = ajAcdGetInt("seed");
emboss_initseed(inseed, &inseed0, seed);
if(jackknife || bootstrap || permute) {
phyloweights = ajAcdGetProperties("weights");
if(phyloweights) weights = true;
phyloanc = ajAcdGetProperties("ancfile");
if(phyloanc) {
ancvar = true;
embossoutancfile = ajAcdGetOutfile("outancfile");
emboss_openfile(embossoutancfile, &outancfile, &outancfilename);
}
phylomix = ajAcdGetProperties("mixfile");
if(phylomix) {
mixture = true;
embossoutmixfile = ajAcdGetOutfile("outmixfile");
emboss_openfile(embossoutmixfile, &outmixfile, &outmixfilename);
}
if(!permute) {
justweights = ajAcdGetListSingle("justweights");
if(ajStrMatchC(justweights, "j")) justwts = true;
}
}
}
printdata = ajAcdGetBoolean("printdata");
if(printdata) dotdiff = ajAcdGetBoolean("dotdiff");
progress = ajAcdGetBoolean("progress");
embossoutfile = ajAcdGetOutfile("outfile");
emboss_openfile(embossoutfile, &outfile, &outfilename);
} /* emboss_getoptions */
void seqboot_inputnumbersstate(AjPPhyloState state)
{
/* read numbers of species and of sites */
spp = state->Size;
sites = state->Len;
loci = sites;
maxalleles = 1;
} /* seqboot_inputnumberstate */
void seqboot_inputfactors(AjPPhyloProp fact)
{
long i, j;
Char ch, prevch;
AjPStr str;
prevch = ' ';
str = fact->Str[0];
j = 0;
for (i = 0; i < (sites); i++) {
ch = ajStrGetCharPos(str,i);
if (ch != prevch)
j++;
prevch = ch;
factorr[i] = j;
}
} /* seqboot_inputfactors */
void inputoptions()
{
/* input the information on the options */
long weightsum, maxfactsize, i, j, k, l, m;
if (data == genefreqs) {
k = 0;
l = 0;
for (i = 0; i < (loci); i++) {
m = alleles[i];
k++;
for (j = 1; j <= m; j++) {
l++;
factorr[l - 1] = k;
}
}
} else {
for (i = 1; i <= (sites); i++)
factorr[i - 1] = i;
}
if(factors){
seqboot_inputfactors(phylofact);
}
for (i = 0; i < (sites); i++)
oldweight[i] = 1;
if (weights)
inputweightsstr2(phyloweights->Str[0],0, sites, &weightsum, oldweight, &weights, "seqboot");
if (factors && printdata) {
for(i = 0; i < sites; i++)
factor[i] = (char)('0' + (factorr[i]%10));
printfactors(outfile, sites, factor, " (least significant digit)");
}
if (weights && printdata)
printweights(outfile, 0, sites, oldweight, "Sites");
for (i = 0; i < (loci); i++)
how_many[i] = 0;
for (i = 0; i < (loci); i++)
where[i] = 0;
for (i = 1; i <= (sites); i++) {
how_many[factorr[i - 1] - 1]++;
if (where[factorr[i - 1] - 1] == 0)
where[factorr[i - 1] - 1] = i;
}
groups = factorr[sites - 1];
newgroups = 0;
newsites = 0;
maxfactsize = 0;
for(i = 0 ; i < loci ; i++){
if(how_many[i] > maxfactsize){
maxfactsize = how_many[i];
}
}
maxnewsites = groups * maxfactsize;
allocnew();
for (i = 0; i < (groups); i++) {
if (oldweight[where[i] - 1] > 0) {
newgroups++;
newsites += how_many[i];
newwhere[newgroups - 1] = where[i];
newhowmany[newgroups - 1] = how_many[i];
}
}
} /* inputoptions */
void seqboot_inputdatastate(AjPPhyloState state)
{
/* input the names and sequences for each species */
long i, j, k, l, m, n;
Char charstate;
AjPStr str;
boolean allread, done;
nodep = (Char **)Malloc(spp*sizeof(Char *));
for (i = 0; i < (spp); i++)
nodep[i] = (Char *)Malloc(sites*sizeof(Char));
j = nmlngth + (sites + (sites - 1) / 10) / 2 - 5;
if (j < nmlngth - 1)
j = nmlngth - 1;
if (j > 37)
j = 37;
if (printdata) {
fprintf(outfile, "\nBootstrapping algorithm, version %s\n\n\n",VERSION);
if (bootstrap) {
if (blocksize > 1) {
if (regular)
fprintf(outfile, "Block-bootstrap with block size %ld\n\n", blocksize);
else
fprintf(outfile, "Partial (%2.0f%%) block-bootstrap with block size %ld\n\n",
100*fracsample, blocksize);
} else {
if (regular)
fprintf(outfile, "Bootstrap\n\n");
else
fprintf(outfile, "Partial (%2.0f%%) bootstrap\n\n", 100*fracsample);
}
} else {
if (jackknife) {
if (regular)
fprintf(outfile, "Delete-half Jackknife\n\n");
else
fprintf(outfile, "Delete-%2.0f%% Jackknife\n\n", 100*(1.0-fracsample));
} else {
if (permute) {
fprintf(outfile, "Species order permuted separately for each");
if (data == morphology)
fprintf(outfile, " character\n\n");
if (data == restsites)
fprintf(outfile, " site\n\n");
}
else {
if (ild) {
if (data == morphology)
fprintf(outfile, "Character");
if (data == restsites)
fprintf(outfile, "Site");
fprintf(outfile, " order permuted\n\n");
} else {
if (lockhart)
if (data == morphology)
fprintf(outfile, "Character");
if (data == restsites)
fprintf(outfile, "Site");
fprintf(outfile, " order permuted separately for each species\n\n");
}
}
}
}
fprintf(outfile, "%3ld species, ", spp);
if (data == seqs)
fprintf(outfile, "%3ld sites\n\n", sites);
else if (data == morphology)
fprintf(outfile, "%3ld characters\n\n", sites);
else if (data == restsites)
fprintf(outfile, "%3ld sites\n\n", sites);
fprintf(outfile, "Name");
for (i = 1; i <= j; i++)
putc(' ', outfile);
fprintf(outfile, "Data\n");
fprintf(outfile, "----");
for (i = 1; i <= j; i++)
putc(' ', outfile);
fprintf(outfile, "----\n\n");
}
allread = false;
while (!allread) {
allread = true;
i = 1;
while (i <= spp) {
initnamestate(state, i-1);
str = state->Str[i-1];
j = 0;
done = false;
while (!done) {
while (j < sites) {
charstate = ajStrGetCharPos(str, j);
uppercase(&charstate);
j++;
if (charstate == '.')
charstate = nodep[0][j-1];
nodep[i-1][j-1] = charstate;
}
if (j == sites)
done = true;
}
i++;
}
allread = (i > spp);
}
if (!printdata)
return;
m = (sites - 1) / 60 + 1;
for (i = 1; i <= m; i++) {
for (j = 0; j < spp; j++) {
for (k = 0; k < nmlngth; k++)
putc(nayme[j][k], outfile);
fprintf(outfile, " ");
l = i * 60;
if (l > sites)
l = sites;
n = (i - 1) * 60;
for (k = n; k < l; k++) {
if (j + 1 > 1 && nodep[j][k] == nodep[0][k])
charstate = '.';
else
charstate = nodep[j][k];
putc(charstate, outfile);
if ((k + 1) % 10 == 0 && (k + 1) % 60 != 0)
putc(' ', outfile);
}
putc('\n', outfile);
}
putc('\n', outfile);
}
putc('\n', outfile);
} /* seqboot_inputdatastate */
void allocrest()
{ /* allocate memory for bookkeeping arrays */
oldweight = (steptr)Malloc(sites*sizeof(long));
weight = (steptr)Malloc(sites*sizeof(long));
if (categories)
category = (steptr)Malloc(sites*sizeof(long));
if (mixture)
mixdata = (steptr)Malloc(sites*sizeof(long));
if (ancvar)
ancdata = (steptr)Malloc(sites*sizeof(long));
where = (steptr)Malloc(loci*sizeof(long));
how_many = (steptr)Malloc(loci*sizeof(long));
factor = (Char *)Malloc(sites*sizeof(Char));
factorr = (steptr)Malloc(sites*sizeof(long));
nayme = (naym *)Malloc(spp*sizeof(naym));
} /* allocrest */
void allocnew(void)
{ /* allocate memory for arrays that depend on the lenght of the
output sequence*/
long i;
newwhere = (steptr)Malloc(loci*sizeof(long));
newhowmany = (steptr)Malloc(loci*sizeof(long));
newerwhere = (steptr)Malloc(loci*sizeof(long));
newerhowmany = (steptr)Malloc(loci*sizeof(long));
newerfactor = (steptr)Malloc(maxnewsites*maxalleles*sizeof(long));
charorder = (steptr *)Malloc(spp*sizeof(steptr));
for (i = 0; i < spp; i++)
charorder[i] = (steptr)Malloc(maxnewsites*sizeof(long));
}
void doinput(int argc, Char *argv[])
{ /* reads the input data */
seqboot_inputnumbersstate(phylostate[0]);
allocrest();
inputoptions();
seqboot_inputdatastate(phylostate[0]);
} /* doinput */
void bootweights()
{ /* sets up weights by resampling data */
long i, j, k, blocks;
double p, q, r;
ws = newgroups;
for (i = 0; i < (ws); i++)
weight[i] = 0;
if (jackknife) {
if (fabs(newgroups*fracsample - (long)(newgroups*fracsample+0.5))
> 0.00001) {
if (randum(seed)
< (newgroups*fracsample - (long)(newgroups*fracsample))
/((long)(newgroups*fracsample+1.0)-(long)(newgroups*fracsample)))
q = (long)(newgroups*fracsample)+1;
else
q = (long)(newgroups*fracsample);
} else
q = (long)(newgroups*fracsample+0.5);
r = newgroups;
p = q / r;
ws = 0;
for (i = 0; i < (newgroups); i++) {
if (randum(seed) < p) {
weight[i]++;
ws++;
q--;
}
r--;
if (i + 1 < newgroups)
p = q / r;
}
} else if (permute) {
for (i = 0; i < (newgroups); i++)
weight[i] = 1;
} else if (bootstrap) {
blocks = fracsample * newgroups / blocksize;
for (i = 1; i <= (blocks); i++) {
j = (long)(newgroups * randum(seed)) + 1;
for (k = 0; k < blocksize; k++) {
weight[j - 1]++;
j++;
if (j > newgroups)
j = 1;
}
}
} else /* case of rewriting data */
for (i = 0; i < (newgroups); i++)
weight[i] = 1;
for (i = 0; i < (newgroups); i++)
newerwhere[i] = 0;
for (i = 0; i < (newgroups); i++)
newerhowmany[i] = 0;
newergroups = 0;
newersites = 0;
for (i = 0; i < (newgroups); i++) {
for (j = 1; j <= (weight[i]); j++) {
newergroups++;
for (k = 1; k <= (newhowmany[i]); k++) {
newersites++;
newerfactor[newersites - 1] = newergroups;
}
newerwhere[newergroups - 1] = newwhere[i];
newerhowmany[newergroups - 1] = newhowmany[i];
}
}
} /* bootweights */
void sppermute(long n)
{ /* permute the species order as given in array sppord */
long i, j, k;
for (i = 1; i <= (spp - 1); i++) {
k = (long)((i+1) * randum(seed));
j = sppord[n - 1][i];
sppord[n - 1][i] = sppord[n - 1][k];
sppord[n - 1][k] = j;
}
} /* sppermute */
void charpermute(long m, long n)
{ /* permute the n+1 characters of species m+1 */
long i, j, k;
for (i = 1; i <= (n - 1); i++) {
k = (long)((i+1) * randum(seed));
j = charorder[m][i];
charorder[m][i] = charorder[m][k];
charorder[m][k] = j;
}
} /* charpermute */
void writedata()
{
/* write out one set of bootstrapped sequences */
long i, j, k, l, m, n, n2=0;
double x;
Char charstate;
sppord = (long **)Malloc(newergroups*sizeof(long *));
for (i = 0; i < (newergroups); i++)
sppord[i] = (long *)Malloc(spp*sizeof(long));
for (j = 1; j <= spp; j++)
sppord[0][j - 1] = j;
for (i = 1; i < newergroups; i++) {
for (j = 1; j <= (spp); j++)
sppord[i][j - 1] = sppord[i - 1][j - 1];
}
if (!justwts || permute) {
if (data == restsites && enzymes)
fprintf(outfile, "%5ld %5ld% 4ld\n", spp, newergroups, nenzymes);
else if (data == genefreqs)
fprintf(outfile, "%5ld %5ld\n", spp, newergroups);
else {
if ((data == seqs)
&& !(bootstrap || jackknife || permute || ild || lockhart) && xml)
fprintf(outfile, "\n");
else
if (!(bootstrap || jackknife || permute || ild || lockhart) && nexus) {
fprintf(outfile, "#NEXUS\n");
fprintf(outfile, "BEGIN DATA\n");
fprintf(outfile, " DIMENSIONS NTAX=%ld NCHAR=%ld;\n",
spp, newersites);
fprintf(outfile, " FORMAT");
fprintf(outfile, " interleave");
fprintf(outfile, " DATATYPE=");
if (data == seqs) {
switch (seq) {
case (dna): fprintf(outfile, "DNA missing=N gap=-"); break;
case (rna): fprintf(outfile, "RNA missing=N gap=-"); break;
case (protein):
fprintf(outfile, "protein missing=? gap=-");
break;
}
}
if (data == morphology)
fprintf(outfile, "STANDARD");
fprintf(outfile, ";\n MATRIX\n");
}
else fprintf(outfile, "%5ld %5ld\n", spp, newersites);
}
if (data == genefreqs) {
for (i = 0; i < (newergroups); i++)
fprintf(outfile, " %3ld", alleles[factorr[newerwhere[i] - 1] - 1]);
putc('\n', outfile);
}
}
l = 1;
if ((!(bootstrap || jackknife || permute || ild || lockhart | nexus))
&& ((data == seqs) || (data == restsites))) {
interleaved = !interleaved;
if (!(bootstrap || jackknife || permute || ild || lockhart) && xml)
interleaved = false;
}
if (interleaved)
m = 60;
else
m = newergroups;
do {
if (m > newergroups)
m = newergroups;
for (j = 0; j < spp; j++) {
n = 0;
if ((l == 1) || (interleaved && nexus)) {
if (!(bootstrap || jackknife || permute || ild || lockhart) && xml) {
fprintf(outfile, " \n");
fprintf(outfile, " ");
}
n2 = nmlngth-1;
if (!(bootstrap || jackknife || permute || ild || lockhart)
&& (xml || nexus)) {
while (nayme[j][n2] == ' ')
n2--;
}
if (nexus)
fprintf(outfile, " ");
for (k = 0; k <= n2; k++)
if (nexus && (nayme[j][k] == ' ') && (k < n2))
putc('_', outfile);
else
putc(nayme[j][k], outfile);
if (!(bootstrap || jackknife || permute || ild || lockhart) && xml)
fprintf(outfile, "\n ");
} else {
if (!(bootstrap || jackknife || permute || ild || lockhart) && xml) {
fprintf(outfile, " ");
}
else {
for (k = 1; k <= nmlngth; k++)
putc(' ', outfile);
}
}
if (nexus)
for (k = 0; k < nmlngth+1-n2; k++)
fprintf(outfile, " ");
for (k = l - 1; k < m; k++) {
if (permute && j + 1 == 1)
sppermute(newerfactor[n]); /* we can assume chars not permuted */
for (n2 = -1; n2 <= (newerhowmany[k] - 2); n2++) {
n++;
if (data == genefreqs) {
if (n > 1 && (n & 7) == 1)
fprintf(outfile, "\n ");
x = nodef[sppord[newerfactor[charorder[j][n - 1]] - 1][j] - 1]
[newerwhere[charorder[j][k]] + n2];
fprintf(outfile, "%8.5f", x);
} else {
if (!(bootstrap || jackknife || permute || ild || lockhart) && xml
&& (n > 1) && (n % 60 == 1))
fprintf(outfile, "\n ");
else if (!nexus && !interleaved && (n > 1) && (n % 60 == 1))
fprintf(outfile, "\n ");
charstate = nodep[sppord[newerfactor[charorder[j][n - 1]] - 1]
[j] - 1][newerwhere[charorder[j][k]] + n2];
putc(charstate, outfile);
if (n % 10 == 0 && n % 60 != 0)
putc(' ', outfile);
}
}
}
if (!(bootstrap || jackknife || permute || ild || lockhart ) && xml) {
fprintf(outfile, "\n \n");
}
putc('\n', outfile);
}
if (interleaved) {
if ((m <= newersites) && (newersites > 60))
putc('\n', outfile);
l += 60;
m += 60;
}
} while (interleaved && l <= newersites);
if ((data == seqs) &&
(!(bootstrap || jackknife || permute || ild || lockhart) && xml))
fprintf(outfile, "\n");
if (!(bootstrap || jackknife || permute || ild || lockhart) && nexus)
fprintf(outfile, " ;\nEND;\n");
for (i = 0; i < (newergroups); i++)
free(sppord[i]);
free(sppord);
} /* writedata */
void writeweights()
{ /* write out one set of post-bootstrapping weights */
long j, k, l, m, n, o;
j = 0;
l = 1;
if (interleaved)
m = 60;
else
m = sites;
do {
if(m > sites)
m = sites;
n = 0;
for (k = l - 1; k < m; k++) {
for(o = 0 ; o < how_many[k] ; o++){
if(oldweight[k]==0){
fprintf(outweightfile, "0");
j++;
}
else{
if (weight[k-j] < 10)
fprintf(outweightfile, "%c", (char)('0'+weight[k-j]));
else
fprintf(outweightfile, "%c", (char)('A'+weight[k-j]-10));
n++;
if (!interleaved && n > 1 && n % 60 == 1) {
fprintf(outweightfile, "\n");
if (n % 10 == 0 && n % 60 != 0)
putc(' ', outweightfile);
}
}
}
}
putc('\n', outweightfile);
if (interleaved) {
l += 60;
m += 60;
}
} while (interleaved && l <= sites);
} /* writeweights */
void writecategories()
{
/* write out categories for the bootstrapped sequences */
long k, l, m, n, n2;
Char charstate;
if(justwts){
if (interleaved)
m = 60;
else
m = sites;
l=1;
do {
if(m > sites)
m = sites;
n=0;
for(k=l-1 ; k < m ; k++){
n++;
if (!interleaved && n > 1 && n % 60 == 1)
fprintf(outcatfile, "\n ");
charstate = '0' + category[k];
putc(charstate, outcatfile);
}
if (interleaved) {
l += 60;
m += 60;
}
}while(interleaved && l <= sites);
fprintf(outcatfile, "\n");
return;
}
l = 1;
if (interleaved)
m = 60;
else
m = newergroups;
do {
if (m > newergroups)
m = newergroups;
n = 0;
for (k = l - 1; k < m; k++) {
for (n2 = -1; n2 <= (newerhowmany[k] - 2); n2++) {
n++;
if (!interleaved && n > 1 && n % 60 == 1)
fprintf(outcatfile, "\n ");
charstate = '0' + category[newerwhere[k] + n2];
putc(charstate, outcatfile);
if (n % 10 == 0 && n % 60 != 0)
putc(' ', outcatfile);
}
}
if (interleaved) {
l += 60;
m += 60;
}
} while (interleaved && l <= newersites);
fprintf(outcatfile, "\n");
} /* writecategories */
void writeauxdata(steptr auxdata, FILE *outauxfile)
{
/* write out auxiliary option data (mixtures, ancestors, ect) to
appropriate file. Samples parralel to data, or just gives one
output entry if justwts is true */
long k, l, m, n, n2;
Char charstate;
/* if we just output weights (justwts), and this is first set
just output the data unsampled */
if(justwts){
if(firstrep){
if (interleaved)
m = 60;
else
m = sites;
l=1;
do {
if(m > sites)
m = sites;
n = 0;
for(k=l-1 ; k < m ; k++){
n++;
if (!interleaved && n > 1 && n % 60 == 1)
fprintf(outauxfile, "\n ");
charstate = auxdata[k];
putc(charstate, outauxfile);
}
if (interleaved) {
l += 60;
m += 60;
}
}while(interleaved && l <= sites);
fprintf(outauxfile, "\n");
}
return;
}
l = 1;
if (interleaved)
m = 60;
else
m = newergroups;
do {
if (m > newergroups)
m = newergroups;
n = 0;
for (k = l - 1; k < m; k++) {
for (n2 = -1; n2 <= (newerhowmany[k] - 2); n2++) {
n++;
if (!interleaved && n > 1 && n % 60 == 1)
fprintf(outauxfile, "\n ");
charstate = auxdata[newerwhere[k] + n2];
putc(charstate, outauxfile);
if (n % 10 == 0 && n % 60 != 0)
putc(' ', outauxfile);
}
}
if (interleaved) {
l += 60;
m += 60;
}
} while (interleaved && l <= newersites);
fprintf(outauxfile, "\n");
} /* writeauxdata */
void writefactors(void)
{
long k, l, m, n, prevfact, writesites;
char symbol;
steptr wfactor;
if(!justwts || firstrep){
if(justwts){
writesites = sites;
wfactor = factorr;
} else {
writesites = newersites;
wfactor = newerfactor;
}
prevfact = wfactor[0];
symbol = '+';
if (interleaved)
m = 60;
else
m = writesites;
l=1;
do {
if(m > writesites)
m = writesites;
n = 0;
for(k=l-1 ; k < m ; k++){
n++;
if (!interleaved && n > 1 && n % 60 == 1)
fprintf(outfactfile, "\n ");
if(prevfact != wfactor[k]){
symbol = (symbol == '+') ? '-' : '+';
prevfact = wfactor[k];
}
putc(symbol, outfactfile);
if (n % 10 == 0 && n % 60 != 0)
putc(' ', outfactfile);
}
if (interleaved) {
l += 60;
m += 60;
}
}while(interleaved && l <= writesites);
fprintf(outfactfile, "\n");
}
} /* writefactors */
void bootwrite()
{ /* does bootstrapping and writes out data sets */
long i, j, rr, repdiv10;
if (!(bootstrap || jackknife || permute || ild || lockhart))
reps = 1;
repdiv10 = reps / 10;
if (repdiv10 < 1)
repdiv10 = 1;
if (progress)
putchar('\n');
for (rr = 1; rr <= (reps); rr++) {
for (i = 0; i < spp; i++)
for (j = 0; j < maxnewsites; j++)
charorder[i][j] = j;
if(rr==1)
firstrep = true;
else
firstrep = false;
if (ild) {
charpermute(0, maxnewsites);
for (i = 1; i < spp; i++)
for (j = 0; j < maxnewsites; j++)
charorder[i][j] = charorder[0][j];
}
if (lockhart)
for (i = 0; i < spp; i++)
charpermute(i, maxnewsites);
bootweights();
if (!justwts || permute || ild || lockhart)
writedata();
if (justwts && !(permute || ild || lockhart))
writeweights();
if (categories)
writecategories();
if (factors)
writefactors();
if (mixture)
writeauxdata(mixdata, outmixfile);
if (ancvar)
writeauxdata(ancdata, outancfile);
if (progress && (bootstrap || jackknife || permute || ild || lockhart)
&& ((reps < 10) || rr % repdiv10 == 0)) {
printf("completed replicate number %4ld\n", rr);
#ifdef WIN32
phyFillScreenColor();
#endif
}
}
if (progress) {
if (justwts)
printf("\nOutput weights written to file \"%s\"\n\n", outweightfilename);
else
printf("\nOutput written to file \"%s\"\n\n", outfilename);
}
} /* bootwrite */
int main(int argc, Char *argv[])
{ /* Read in sequences or frequencies and bootstrap or jackknife them */
#ifdef MAC
argc = 1; /* macsetup("SeqBoot",""); */
argv[0] = "SeqBoot";
#endif
init(argc,argv);
emboss_getoptions("fdiscboot", argc, argv);
ibmpc = IBMCRT;
ansi = ANSICRT;
doinput(argc, argv);
bootwrite();
FClose(infile);
if (weights)
FClose(weightfile);
if (categories) {
FClose(catfile);
FClose(outcatfile);
}
if(mixture)
FClose(outmixfile);
if(ancvar)
FClose(outancfile);
if (justwts && !permute) {
FClose(outweightfile);
}
else
FClose(outfile);
#ifdef MAC
fixmacfile(outfilename);
if (justwts && !permute)
fixmacfile(outweightfilename);
if (categories)
fixmacfile(outcatfilename);
if (mixture)
fixmacfile(outmixfilename);
#endif
if(progress)
printf("Done.\n\n");
#ifdef WIN32
phyRestoreConsoleAttributes();
#endif
embExit();
return 0;
}
PHYLIPNEW-3.69.650/src/phylip.c 0000664 0001750 0001750 00000216764 11605067345 012555 0000000 0000000
/* version 3.6. (c) Copyright 1993-2002 by the University of Washington.
Written by Joseph Felsenstein, Akiko Fuseki, Sean Lamont, Andrew Keeffe,
and Dan Fineman.
Permission is granted to copy and use this program provided no fee is
charged for it and provided that this copyright notice is not removed. */
#ifdef OSX_CARBON
#include
#endif /* OSX_CARBON */
#include
#include
#include "phylip.h"
#ifdef WIN32
#include
/* for console code (clear screen, text color settings) */
CONSOLE_SCREEN_BUFFER_INFO savecsbi;
boolean savecsbi_valid = false;
HANDLE hConsoleOutput;
void phyClearScreen();
void phySaveConsoleAttributes();
void phySetConsoleAttributes();
void phyRestoreConsoleAttributes();
void phyFillScreenColor();
#endif
static void emboss_printtreenode(node *p, node* root);
long countsemic(char *treestr);
#if defined(OSX_CARBON) && defined(__MWERKS__)
boolean fixedpath = false;
#endif /* WIN32 */
FILE *outfile, *infile, *intree, *intree2, *outtree, *weightfile, *catfile, *ancfile, *mixfile, *factfile;
AjPFile embossinfile;
AjPFile embossoutfile;
AjPFile embossintree;
AjPFile embossintree2;
AjPFile embossouttree;
AjPFile embossweightfile;
AjPFile embosscatfile;
AjPFile embossancfile;
AjPFile embossmixfile;
AjPFile embossfactfile;
long spp, words, bits;
boolean ibmpc, ansi, tranvsp;
naym *nayme; /* names of species */
void init(int argc, char** argv)
{ /* initialization routine for all programs
* anything done at the beginning for every program should be done here */
/* set up signal handler for
* segfault, floating point exception, illegal instruction, bad pipe, bus error
* there are more signals that can cause a crash, but these are the most common
* even these aren't found on all machines. */
}
int filexists(char *filename)
{ /* check whether file already exists */
FILE *fp;
fp =fopen(filename,"r");
if (fp) {
fclose(fp);
return 1;
} else
return 0;
} /*filexists*/
const char* get_command_name (const char *vektor)
{ /* returns the name of the program from vektor without the whole path */
char *last_slash;
/* Point to the last slash... */
last_slash = strrchr (vektor, DELIMITER);
if (last_slash)
/* If there was a last slash, return the character after it */
return last_slash + 1;
else
/* If not, return the vector */
return vektor;
} /* get_command_name */
void EOF_error()
{ /* Print a message and exit when EOF is reached prematurely. */
puts("\n\nERROR: Unexpected end-of-file.\n");
exxit(-1);
} /* EOF_error */
void getstryng(char *fname)
{ /* read in a file name from stdin and take off newline if any */
char *end;
fflush(stdout);
fname = fgets(fname, FNMLNGTH, stdin);
if ( fname == NULL )
EOF_error();
if ( (end = strpbrk(fname, "\n\r")) != NULL)
*end = '\0';
} /* getstryng */
void countup(long *loopcount, long maxcount)
{ /* count how many times this loop has tried to read data, bail out
if exceeds maxcount */
(*loopcount)++;
if ((*loopcount) >= maxcount) {
ajErr("Made %ld attempts to read input in loop. Aborting run.",
*loopcount);
exxit(-1);
}
} /* countup */
void emboss_openfile(AjPFile outfile, FILE **fp, const char **perm)
{
if (outfile)
{
*fp = ajFileGetFileptr(outfile);
outfile->fp = NULL;
}
else
*fp = NULL;
ajDebug("phylip emboss_openfile '%F'\n",
outfile);
*perm = ajFileGetNameC(outfile);
return;
}
void cleerhome()
{ /* home cursor and clear screen, if possible */
#ifdef WIN32
if(ibmpc || ansi){
phyClearScreen();
} else {
printf("\n\n");
}
#else
printf("%s", ((ibmpc || ansi) ? ("\033[2J\033[H") : "\n\n"));
#endif
} /* cleerhome */
double randum(longer seed)
{ /* random number generator -- slow but machine independent
This is a multiplicative congruential 32-bit generator
x(t+1) = 1664525 * x(t) mod 2^32, one that passes the
Coveyou-Macpherson and Lehmer tests, see Knuth ACP vol. 2
We here implement it representing each integer in base-64
notation -- i.e. as an array of 6 six-bit chunks */
long i, j, k, sum;
longer mult, newseed;
double x;
mult[0] = 13; /* these four statements set the multiplier */
mult[1] = 24; /* -- they are its "digits" in a base-64 */
mult[2] = 22; /* notation: 1664525 = 6*64^3+22*64^2 */
mult[3] = 6; /* +24*64+13 */
for (i = 0; i <= 5; i++)
newseed[i] = 0;
for (i = 0; i <= 5; i++) { /* do the multiplication piecewise */
sum = newseed[i];
k = i;
if (i > 3)
k = 3;
for (j = 0; j <= k; j++)
sum += mult[j] * seed[i - j];
newseed[i] = sum;
for (j = i; j <= 4; j++) {
newseed[j + 1] += newseed[j] / 64;
newseed[j] &= 63;
}
}
memcpy(seed, newseed, sizeof(longer)); /* new seed replaces old one */
seed[5] &= 3; /* from the new seed, get a floating point fraction */
x = 0.0;
for (i = 0; i <= 5; i++)
x = x / 64.0 + seed[i];
x /= 4.0;
return x;
} /* randum */
void randumize(longer seed, long *enterorder)
{ /* randomize input order of species -- randomly permute array enterorder */
long i, j, k;
for (i = 0; i < spp; i++) {
j = (long)(randum(seed) * (i+1));
k = enterorder[j];
enterorder[j] = enterorder[i];
enterorder[i] = k;
}
} /* randumize */
double normrand(longer seed)
{/* standardized Normal random variate */
double x;
x = randum(seed)+randum(seed)+randum(seed)+randum(seed)
+ randum(seed)+randum(seed)+randum(seed)+randum(seed)
+ randum(seed)+randum(seed)+randum(seed)+randum(seed)-6.0;
return(x);
} /* normrand */
void uppercase(Char *ch)
{ /* convert ch to upper case */
*ch = (islower ((int)*ch) ? toupper((int)*ch) : ((int)*ch));
} /* uppercase */
/* @func emboss_initseed ******************************************************
**
** Given a random number seed (inseed)
**
** Increments it until it gives a remainder of 1 when divided by 4
** and returns the resulting corrected seed as *inseed0
**
** Also returns an array of 6 seed values in seed array
**
******************************************************************************/
void emboss_initseed(long inseed, long *inseed0, longer seed)
{ /* input random number seed */
long i;
long myinseed = inseed;
while ((myinseed & 3)!=1) /* must be an 4n+1 - see main.html */
myinseed++;
*inseed0 = myinseed;
for (i = 0; i <= 5; i++)
seed[i] = 0;
i = 0;
do {
seed[i] = myinseed & 63;
myinseed /= 64;
i++;
} while (myinseed != 0);
} /*emboss_initseed*/
void emboss_initoutgroup(long *outgrno, long spp)
{ /* validate outgroup number against number of species */
if (spp < 1)
{
ajDie("Cannot set outgroup number: species count spp %ld less than 1",
spp);
}
if (*outgrno > spp)
{
ajWarn("Bad outgroup number: %ld, set to maximum group %ld",
*outgrno, spp);
*outgrno = spp;
}
ajDebug("emboss_initoutgroup spp: %ld => outgrno %ld\n", spp, *outgrno);
} /*initoutgroup*/
void emboss_initcatn(long *categs)
{ /* initialize category number for rate categories */
if (*categs > maxcategs)
*categs = maxcategs;
} /*initcatn*/
void emboss_initcategs(AjPFloat arrayvals, long categs, double *rate)
{ /* initialize category rates */
long i;
long maxi;
if (!rate) return;
maxi = ajFloatLen(arrayvals);
if (maxi != categs)
ajWarn("HMM category rates read %d values, expected %d values",
maxi, categs);
for (i=0; i < categs; i++)
{
if (i > maxi)
rate[i] = 0.0;
else
rate[i] = ajFloatGet(arrayvals, i);
}
} /*initrcategs*/
double emboss_initprobcat(AjPFloat arrayvals, long categs, double *probcat)
{ /* input probabilities of rate categories for HMM rates */
long i;
long maxi;
double probsum = 0.0;
if (!categs)
return probsum;
maxi = ajFloatLen(arrayvals);
if (maxi != categs)
ajWarn("Category probabilities read %d values, expected %d values",
maxi, categs);
for (i=0; i < categs; i++)
{
if (i > maxi)
probcat[i] = 0.0;
else
probcat[i] = ajFloatGet(arrayvals, i);
probsum += probcat[i];
}
return probsum;
} /*initprobcat*/
void lgr(long m, double b, raterootarray lgroot)
{ /* For use by initgammacat. Get roots of m-th Generalized Laguerre
polynomial, given roots of (m-1)-th, these are to be
stored in lgroot[m][] */
long i;
double upper, lower, x, y;
boolean dwn; /* is function declining in this interval? */
if (m == 1) {
lgroot[1][1] = 1.0+b;
} else {
dwn = true;
for (i=1; i<=m; i++) {
if (i < m) {
if (i == 1)
lower = 0.0;
else
lower = lgroot[m-1][i-1];
upper = lgroot[m-1][i];
} else { /* i == m, must search above */
lower = lgroot[m-1][i-1];
x = lgroot[m-1][m-1];
do {
x = 2.0*x;
y = glaguerre(m, b, x);
} while ((dwn && (y > 0.0)) || ((!dwn) && (y < 0.0)));
upper = x;
}
while (upper-lower > 0.000000001) {
x = (upper+lower)/2.0;
if (glaguerre(m, b, x) > 0.0) {
if (dwn)
lower = x;
else
upper = x;
} else {
if (dwn)
upper = x;
else
lower = x;
}
}
lgroot[m][i] = (lower+upper)/2.0;
dwn = !dwn; /* switch for next one */
}
}
} /* lgr */
double logfac (long n)
{ /* log(n!) values were calculated with Mathematica
with a precision of 30 digits */
long i;
double x;
switch (n)
{
case 0:
return 0.;
case 1:
return 0.;
case 2:
return 0.693147180559945309417232121458;
case 3:
return 1.791759469228055000812477358381;
case 4:
return 3.1780538303479456196469416013;
case 5:
return 4.78749174278204599424770093452;
case 6:
return 6.5792512120101009950601782929;
case 7:
return 8.52516136106541430016553103635;
case 8:
return 10.60460290274525022841722740072;
case 9:
return 12.80182748008146961120771787457;
case 10:
return 15.10441257307551529522570932925;
case 11:
return 17.50230784587388583928765290722;
case 12:
return 19.98721449566188614951736238706;
default:
x = 19.98721449566188614951736238706;
for (i = 13; i <= n; i++)
x += log(i);
return x;
}
} /* logfac */
double glaguerre(long m, double b, double x)
{ /* Generalized Laguerre polynomial computed recursively.
For use by initgammacat */
long i;
double gln, glnm1, glnp1; /* L_n, L_(n-1), L_(n+1) */
if (m == 0)
return 1.0;
else {
if (m == 1)
return 1.0 + b - x;
else {
gln = 1.0+b-x;
glnm1 = 1.0;
for (i=2; i <= m; i++) {
glnp1 = ((2*(i-1)+b+1.0-x)*gln - (i-1+b)*glnm1)/i;
glnm1 = gln;
gln = glnp1;
}
return gln;
}
}
} /* glaguerre */
void initlaguerrecat(long categs, double alpha, double *rate, double *probcat)
{ /* calculate rates and probabilities to approximate Gamma distribution
of rates with "categs" categories and shape parameter "alpha" using
rates and weights from Generalized Laguerre quadrature */
long i;
raterootarray lgroot; /* roots of GLaguerre polynomials */
double f, x, xi, y;
alpha = alpha - 1.0;
lgroot[1][1] = 1.0+alpha;
for (i = 2; i <= categs; i++)
lgr(i, alpha, lgroot); /* get roots for L^(a)_n */
/* here get weights */
/* Gamma weights are (1+a)(1+a/2) ... (1+a/n)*x_i/((n+1)^2 [L_{n+1}^a(x_i)]^2) */
f = 1;
for (i = 1; i <= categs; i++)
f *= (1.0+alpha/i);
for (i = 1; i <= categs; i++) {
xi = lgroot[categs][i];
y = glaguerre(categs+1, alpha, xi);
x = f*xi/((categs+1)*(categs+1)*y*y);
rate[i-1] = xi/(1.0+alpha);
probcat[i-1] = x;
}
} /* initlaguerrecat */
double hermite(long n, double x)
{ /* calculates hermite polynomial with degree n and parameter x */
/* seems to be unprecise for n>13 -> root finder does not converge*/
double h1 = 1.;
double h2 = 2. * x;
double xx = 2. * x;
long i;
for (i = 1; i < n; i++) {
xx = 2. * x * h2 - 2. * (i) * h1;
h1 = h2;
h2 = xx;
}
return xx;
} /* hermite */
void root_hermite(long n, double *hroot)
{ /* find roots of Hermite polynmials */
long z;
long ii;
long start;
if (n % 2 == 0) {
start = n/2;
z = 1;
} else {
start = n/2 + 1;
z=2;
hroot[start-1] = 0.0;
}
for (ii = start; ii < n; ii++) { /* search only upwards*/
hroot[ii] = halfroot(hermite, n, hroot[ii-1]+EPSILON, 1./n);
hroot[start - z] = -hroot[ii];
z++;
}
} /* root_hermite */
double halfroot(double (*func)(long m, double x), long n, double startx,
double delta)
{ /* searches from the bound (startx) only in one direction
(by positive or negative delta, which results in
other-bound=startx+delta)
delta should be small.
(*func) is a function with two arguments */
double xl;
double xu;
double xm = 0.0;
double fu;
double fl;
double fm = 100000.;
double gradient;
boolean dwn = false;
/* decide if we search above or below startx and escapes to trace back
to the starting point that most often will be
the root from the previous calculation */
if (delta < 0) {
xu = startx;
xl = xu + delta;
} else {
xl = startx;
xu = xl + delta;
}
delta = fabs(delta);
fu = (*func)(n, xu);
fl = (*func)(n, xl);
gradient = (fl-fu)/(xl-xu);
while(fabs(fm) > EPSILON) { /* is root outside of our bracket?*/
if ((fu<0.0 && fl<0.0) || (fu>0.0 && fl > 0.0)) {
xu += delta;
fu = (*func)(n, xu);
fl = (*func)(n, xl);
gradient = (fl-fu)/(xl-xu);
dwn = (gradient < 0.0) ? true : false;
} else {
xm = xl - fl / gradient;
fm = (*func)(n, xm);
if (dwn) {
if (fm > 0.) {
xl = xm;
fl = fm;
} else {
xu = xm;
fu = fm;
}
} else {
if (fm > 0.) {
xu = xm;
fu = fm;
} else {
xl = xm;
fl = fm;
}
}
gradient = (fl-fu)/(xl-xu);
}
}
return xm;
} /* halfroot */
void hermite_weight(long n, double * hroot, double * weights)
{
/* calculate the weights for the hermite polynomial at the roots
using formula from Abramowitz and Stegun chapter 25.4.46 p.890 */
long i;
double hr2;
double numerator;
numerator = exp(0.6931471805599 * ( n-1.) + logfac(n)) / (n*n);
for (i = 0; i < n; i++) {
hr2 = hermite(n-1, hroot[i]);
weights[i] = numerator / (hr2*hr2);
}
} /* hermiteweight */
void inithermitcat(long categs, double alpha, double *rate, double *probcat)
{ /* calculates rates and probabilities */
long i;
double *hroot;
double std;
std = SQRT2 /sqrt(alpha);
hroot = (double *) Malloc((categs+1) * sizeof(double));
root_hermite(categs, hroot); /* calculate roots */
hermite_weight(categs, hroot, probcat); /* set weights */
for (i=0; i= 100.0)
inithermitcat(categs, alpha, rate, probcat);
else
initlaguerrecat(categs, alpha, rate, probcat);
} /* initgammacat */
void inithowmany(long *howmanny, long howoften)
{/* input how many cycles */
long loopcount;
loopcount = 0;
for (;;) {
printf("How many cycles of %4ld trees?\n", howoften);
fflush(stdout);
if (scanf("%ld%*[^\n]", howmanny) == 1) {
getchar();
if (*howmanny >= 1)
break;
}
countup(&loopcount, 10);
}
} /*inithowmany*/
void inithowoften(long *howoften)
{ /* input how many trees per cycle */
long loopcount;
loopcount = 0;
for (;;) {
printf("How many trees per cycle?\n");
fflush(stdout);
if (scanf("%ld%*[^\n]", howoften) == 1) {
getchar();
if (*howoften >= 1)
break;
}
countup(&loopcount, 10);
}
} /*inithowoften*/
void initlambda(double *lambda)
{ /* input patch length parameter for autocorrelated HMM rates */
long loopcount;
loopcount = 0;
for (;;) {
printf("Mean block length of sites having the same rate (greater than 1)?\n");
fflush(stdout);
if (scanf("%lf%*[^\n]", lambda) == 1) {
getchar();
if (*lambda > 1.0)
break;
}
countup(&loopcount, 10);
}
*lambda = 1.0 / *lambda;
} /* initlambda */
void initfreqs(double *freqa, double *freqc, double *freqg, double *freqt)
{ /* input frequencies of the four bases */
char input[100];
long scanned, loopcount;
printf("Base frequencies for A, C, G, T/U (use blanks to separate)?\n");
loopcount = 0;
do {
fflush(stdout);
getstryng(input);
scanned = sscanf(input,"%lf%lf%lf%lf%*[^\n]", freqa, freqc, freqg, freqt);
if (scanned == 4)
break;
else
printf("Please enter exactly 4 values.\n");
countup(&loopcount, 100);
} while (1);
} /* initfreqs */
void initratio(double *ttratio)
{ /* input transition/transversion ratio */
long loopcount;
loopcount = 0;
for (;;) {
printf("Transition/transversion ratio?\n");
fflush(stdout);
if (scanf("%lf%*[^\n]", ttratio) == 1) {
getchar();
if (*ttratio >= 0.0)
break;
else
printf("Transition/transversion ratio cannot be negative.\n");
}
countup(&loopcount, 10);
}
} /* initratio */
void initpower(double *power)
{
for (;;) {
printf("New power?\n");
fflush(stdout);
if (scanf("%lf%*[^\n]", power) == 1) {
getchar();
break;
}
}
} /* initpower */
void initdatasets(long *datasets)
{
/* handle multi-data set option */
long loopcount;
loopcount = 0;
for (;;) {
printf("How many data sets?\n");
fflush(stdout);
if (scanf("%ld%*[^\n]", datasets) == 1) {
getchar();
if (*datasets > 1)
break;
else
printf("Bad data sets number: it must be greater than 1\n");
}
countup(&loopcount, 10);
}
} /* initdatasets */
void justweights(long *datasets)
{
/* handle multi-data set option by weights */
long loopcount;
loopcount = 0;
for (;;) {
printf("How many sets of weights?\n");
fflush(stdout);
if (scanf("%ld%*[^\n]", datasets) == 1) {
getchar();
if (*datasets >= 1)
break;
else
printf("BAD NUMBER: it must be greater than 1\n");
}
countup(&loopcount, 10);
}
} /* justweights */
void initterminal(boolean *ibmpc, boolean *ansi)
{
/* handle terminal option */
if (*ibmpc) {
*ibmpc = false;
*ansi = true;
} else if (*ansi)
*ansi = false;
else
*ibmpc = true;
} /*initterminal*/
void initbestrees(bestelm *bestrees, long maxtrees, boolean glob)
{
/* initializes either global or local field of each array in bestrees */
long i;
if (glob)
for (i = 0; i < maxtrees; i++)
bestrees[i].gloreange = false;
else
for (i = 0; i < maxtrees; i++)
bestrees[i].locreange = false;
} /* initbestrees */
void newline(FILE *filename, long i, long j, long k)
{
/* go to new line if i is a multiple of j, indent k spaces */
long m;
if ((i - 1) % j != 0 || i <= 1)
return;
putc('\n', filename);
for (m = 1; m <= k; m++)
putc(' ', filename);
} /* newline */
void inputnumbersseq(AjPSeqset seqset,
long *spp, long *chars, long *nonodes, long n)
{
int begin2,end2;
/* input the numbers of species and of characters */
/* revised for EMBOSS to take numbers from seqset input */
ajSeqsetFmtUpper(seqset);
*spp = ajSeqsetGetSize(seqset);
*chars = ajSeqsetGetRange(seqset,&begin2,&end2);
*nonodes = *spp * 2 - n;
ajDebug("inputnumbersseq n: %ld spp: %ld chars: %ld nonodes: %ld\n",
n, *spp, *chars, *nonodes);
} /* inputnumbersseq */
void inputnumbersfreq(AjPPhyloFreq freq,
long *spp, long *chars, long *nonodes, long n)
{
*spp = freq->Size;
*chars = freq->Loci;
*nonodes = *spp * 2 - n;
}
void inputnumbersstate(AjPPhyloState state,
long *spp, long *chars, long *nonodes, long n)
{
ajDebug("inputnumbersstate size %d len %d\n",
state->Size, state->Len);
*spp = state->Size;
*chars = state->Len;
*nonodes = *spp * 2 - n;
}
void inputnumbers2seq(AjPPhyloDist dist, long *spp, long *nonodes, long n)
{
*spp = dist->Size;
fprintf(outfile, "\n%4ld Populations\n", *spp);
*nonodes = *spp * 2 - n;
} /* inputnumbers2seq */
void samenumspfreq(AjPPhyloFreq freq, long *chars, long ith)
{
/* check if spp is same as the first set in other data sets */
if (freq->Size != spp) {
ajErr("\nERROR: Inconsistent number of species in data set %ld", ith);
exxit(-1);
}
*chars = freq->Loci;
} /* samenumspfreq */
void samenumspstate(AjPPhyloState state, long *chars, long ith)
{
/* check if spp is same as the first set in other data sets */
if (state->Size != spp) {
ajErr("\nERROR: Inconsistent number of species in data set %ld", ith);
exxit(-1);
}
*chars = state->Len;
} /* samenumspstate */
void samenumspseq(AjPSeqset set, long *chars, long ith)
{
/* check if spp is same as the first set in other data sets */
if (set->Size != spp) {
ajErr("\nERROR: Inconsistent number of species in data set %ld", ith);
exxit(-1);
}
*chars = set->Len;
} /* samenumspstate */
void samenumspseq2(AjPPhyloDist set, long ith)
{
/* check if spp is same as the first set in other data sets */
if (set->Size != spp) {
ajErr("\nERROR: Inconsistent number of species in data set %ld", ith);
exxit(-1);
}
} /* samenumspphylodist */
void inputweightsstr(AjPStr wtstr,
long chars, steptr weight, boolean *weights)
{
Char ch;
int i;
for (i = 0; i < chars; i++)
{
ch = ajStrGetCharPos(wtstr, i);
weight[i] = 1;
if (isdigit((int) ch))
weight[i] = ch - '0';
else if (isalpha((int) ch))
{
uppercase(&ch);
weight[i] = ch - 'A' + 10;
}
else
{
ajErr("ERROR: Bad weight character: %c", ch);
exxit(-1);
}
}
*weights = true;
} /*inputweightsstr*/
void inputweightsstr2(AjPStr str, long a, long b, long *weightsum,
steptr weight, boolean *weights, const char *prog)
{
/* input the character weights, 0 or 1 */
Char ch = '\0';
long i;
*weightsum = 0;
for (i = a; i < b; i++) {
ch = ajStrGetCharPos(str, i-1);
weight[i] = 1;
if (ch == '0' || ch == '1')
weight[i] = ch - '0';
else {
ajErr("ERROR: Bad weight character: %c -- "
"weights in %s must be 0 or 1\n", ch, prog);
exxit(-1);
}
*weightsum += weight[i];
}
*weights = true;
}
void printweights(FILE *filename, long inc, long chars,
steptr weight, const char *letters)
{
/* print out the weights of sites */
long i, j;
boolean letterweights;
letterweights = false;
for (i = 0; i < chars; i++)
if (weight[i] > 9)
letterweights = true;
fprintf(filename, "\n %s are weighted as follows:", letters);
if (letterweights)
fprintf(filename, " (A = 10, B = 11, etc.)\n");
else
putc('\n', filename);
for (i = 0; i < chars; i++) {
if (i % 60 == 0) {
putc('\n', filename);
for (j = 1; j <= nmlngth + 3; j++)
putc(' ', filename);
}
if (weight[i+inc] < 10)
fprintf(filename, "%ld", weight[i + inc]);
else
fprintf(filename, "%c", 'A'-10+(int)weight[i + inc]);
if ((i+1) % 5 == 0 && (i+1) % 60 != 0)
putc(' ', filename);
}
fprintf(filename, "\n\n");
} /* printweights */
void inputcategsstr(AjPStr str, long a, long b,
steptr category, long categs, const char *prog)
{
/* input the categories, 1-9 */
Char ch;
long i;
for (i = a; i < b; i++) {
ch = ajStrGetCharPos(str, i);
if ((ch >= '1') && (ch <= ('0'+categs)))
category[i] = ch - '0';
}
}
void printcategs(FILE *filename, long chars, steptr category,
const char *letters)
{
/* print out the sitewise categories */
long i, j;
fprintf(filename, "\n %s are:\n", letters);
for (i = 0; i < chars; i++) {
if (i % 60 == 0) {
putc('\n', filename);
for (j = 1; j <= nmlngth + 3; j++)
putc(' ', filename);
}
fprintf(filename, "%ld", category[i]);
if ((i+1) % 10 == 0 && (i+1) % 60 != 0)
putc(' ', filename);
}
fprintf(filename, "\n\n");
} /* printcategs */
void inputfactorsstr(AjPStr str, long chars, Char *factor, boolean *factors)
{
/* reads the factor symbols */
long i;
for (i = 0; i < (chars); i++) {
factor[i] = ajStrGetCharPos(str, i);
}
*factors = true;
} /* inputfactorsnew */
void printfactors(FILE *filename, long chars, Char *factor, const char *letters)
{
/* print out list of factor symbols */
long i;
fprintf(filename, "Factors%s:\n\n", letters);
for (i = 1; i <= nmlngth - 5; i++)
putc(' ', filename);
for (i = 1; i <= (chars); i++) {
newline(filename, i, 55, nmlngth + 3);
putc(factor[i - 1], filename);
if (i % 5 == 0)
putc(' ', filename);
}
putc('\n', filename);
} /* printfactors */
void headings(long chars, const char *letters1, const char *letters2)
{
long i, j;
putc('\n', outfile);
j = nmlngth + (chars + (chars - 1) / 10) / 2 - 5;
if (j < nmlngth - 1)
j = nmlngth - 1;
if (j > 37)
j = 37;
fprintf(outfile, "Name");
for (i = 1; i <= j; i++)
putc(' ', outfile);
fprintf(outfile, "%s\n", letters1);
fprintf(outfile, "----");
for (i = 1; i <= j; i++)
putc(' ', outfile);
fprintf(outfile, "%s\n\n", letters2);
} /* headings */
void initnamestate(AjPPhyloState state, long i)
{
/* read in species name */
long j;
AjPStr names = state->Names[i];
for (j = 0; j < nmlngth; j++) {
if (j < ajStrGetLen(names))
nayme[i][j] = ajStrGetCharPos(names, j);
else
nayme[i][j] = ' ';
if ((nayme[i][j] == '(') || (nayme[i][j] == ')') || (nayme[i][j] == ':')
|| (nayme[i][j] == ',') || (nayme[i][j] == ';') || (nayme[i][j] == '[')
|| (nayme[i][j] == ']')) {
ajErr("\nERROR: Species name may not contain characters ( ) : ; , [ ] \n"
" In name of species number %ld there is character %c\n\n",
i+1, nayme[i][j]);
exxit(-1);
}
}
} /* initnamestate */
void initnamedist(AjPPhyloDist dist, long i)
{
/* read in species name */
long j;
AjPStr names = dist->Names[i];
for (j = 0; j < nmlngth; j++) {
if (j < ajStrGetLen(names))
nayme[i][j] = ajStrGetCharPos(names, j);
else
nayme[i][j] = ' ';
if ((nayme[i][j] == '(') || (nayme[i][j] == ')') || (nayme[i][j] == ':')
|| (nayme[i][j] == ',') || (nayme[i][j] == ';') || (nayme[i][j] == '[')
|| (nayme[i][j] == ']')) {
ajErr("\nERROR: Species name may not contain characters ( ) : ; , [ ] \n"
" In name of species number %ld there is character %c\n\n",
i+1, nayme[i][j]);
exxit(-1);
}
}
} /* initnamedist */
void initnameseq(AjPSeqset set, long i)
{
/* read in species name */
long j;
AjPStr names = ajStrNewS(ajSeqGetNameS(ajSeqsetGetseqSeq(set, i)));
for (j = 0; j < nmlngth; j++) {
if (j < ajStrGetLen(names))
nayme[i][j] = ajStrGetCharPos(names, j);
else
nayme[i][j] = ' ';
if ((nayme[i][j] == '(') || (nayme[i][j] == ')') || (nayme[i][j] == ':')
|| (nayme[i][j] == ',') || (nayme[i][j] == ';') || (nayme[i][j] == '[')
|| (nayme[i][j] == ']')) {
ajErr("\nERROR: Species name may not contain characters ( ) : ; , [ ] \n"
" In name of species number %ld there is character %c\n\n",
i+1, nayme[i][j]);
exxit(-1);
}
}
ajStrDel(&names);
} /* initnameseq */
void initnamefreq(AjPPhyloFreq freq, long i)
{
/* read in species name */
long j;
AjPStr names = freq->Names[i];
for (j = 0; j < nmlngth; j++) {
if (j < ajStrGetLen(names))
nayme[i][j] = ajStrGetCharPos(names, j);
else
nayme[i][j] = ' ';
if ((nayme[i][j] == '(') || (nayme[i][j] == ')') || (nayme[i][j] == ':')
|| (nayme[i][j] == ',') || (nayme[i][j] == ';') || (nayme[i][j] == '[')
|| (nayme[i][j] == ']')) {
ajErr("\nERROR: Species name may not contain characters ( ) : ; , [ ] \n"
" In name of species number %ld there is character %c\n\n",
i+1, nayme[i][j]);
exxit(-1);
}
}
} /* initnamefreq */
void findtree(boolean *found, long *pos, long nextree, long *place,
bestelm *bestrees)
{
/* finds tree given by array place in array bestrees by binary search */
/* used by dnacomp, dnapars, dollop, mix, & protpars */
long i, lower, upper;
boolean below, done;
below = false;
lower = 1;
upper = nextree - 1;
(*found) = false;
while (!(*found) && lower <= upper) {
(*pos) = (lower + upper) / 2;
i = 3;
done = false;
while (!done) {
done = (i > spp);
if (!done)
done = (place[i - 1] != bestrees[(*pos) - 1].btree[i - 1]);
if (!done)
i++;
}
(*found) = (i > spp);
if (*found)
break;
below = (place[i - 1] < bestrees[(*pos )- 1].btree[i - 1]);
if (below)
upper = (*pos) - 1;
else
lower = (*pos) + 1;
}
if (!(*found) && !below)
(*pos)++;
} /* findtree */
void addtree(long pos, long *nextree, boolean collapse, long *place,
bestelm *bestrees)
{
/* puts tree from array place in its proper position in array bestrees */
/* used by dnacomp, dnapars, dollop, mix, & protpars */
long i;
for (i = *nextree - 1; i >= pos; i--){
memcpy(bestrees[i].btree, bestrees[i - 1].btree, spp * sizeof(long));
bestrees[i].gloreange = bestrees[i - 1].gloreange;
bestrees[i - 1].gloreange = false;
bestrees[i].locreange = bestrees[i - 1].locreange;
bestrees[i - 1].locreange = false;
bestrees[i].collapse = bestrees[i - 1].collapse;
}
for (i = 0; i < spp; i++)
bestrees[pos - 1].btree[i] = place[i];
bestrees[pos - 1].collapse = collapse;
(*nextree)++;
} /* addtree */
long findunrearranged(bestelm *bestrees, long nextree, boolean glob)
{
/* finds bestree with either global or local field false */
long i;
if (glob) {
for (i = 0; i < nextree - 1; i++)
if (!bestrees[i].gloreange)
return i;
} else {
for (i = 0; i < nextree - 1; i++)
if (!bestrees[i].locreange)
return i;
}
return -1;
} /* findunrearranged */
boolean torearrange(bestelm *bestrees, long nextree)
{ /* sees if any best tree is yet to be rearranged */
if (findunrearranged(bestrees, nextree, true) >= 0)
return true;
else if (findunrearranged(bestrees, nextree, false) >= 0)
return true;
else
return false;
} /* torearrange */
void reducebestrees(bestelm *bestrees, long *nextree)
{
/* finds best trees with collapsible branches and deletes them */
long i, j;
i = 0;
j = *nextree - 2;
do {
while (!bestrees[i].collapse && i < *nextree - 1) i++;
while (bestrees[j].collapse && j >= 0) j--;
if (i < j) {
memcpy(bestrees[i].btree, bestrees[j].btree, spp * sizeof(long));
bestrees[i].gloreange = bestrees[j].gloreange;
bestrees[i].locreange = bestrees[j].locreange;
bestrees[i].collapse = false;
bestrees[j].collapse = true;
}
} while (i < j);
*nextree = i + 1;
} /* reducebestrees */
void shellsort(double *a, long *b, long n)
{ /* Shell sort keeping a, b in same order */
/* used by dnapenny, dolpenny, & penny */
long gap, i, j, itemp;
double rtemp;
gap = n / 2;
while (gap > 0) {
for (i = gap + 1; i <= n; i++) {
j = i - gap;
while (j > 0) {
if (a[j - 1] > a[j + gap - 1]) {
rtemp = a[j - 1];
a[j - 1] = a[j + gap - 1];
a[j + gap - 1] = rtemp;
itemp = b[j - 1];
b[j - 1] = b[j + gap - 1];
b[j + gap - 1] = itemp;
}
j -= gap;
}
}
gap /= 2;
}
} /* shellsort */
void sgetch(Char *c, long *parens, char **treestr)
{ /* get next nonblank character */
do {
(*c) = *(*treestr)++;
if ((*c) == '\n' || (*c) == '\t')
(*c) = ' ';
} while ( *c == ' ' && (**treestr) );
if ((*c) == '(')
(*parens)++;
if ((*c) == ')')
(*parens)--;
} /* sgetch */
void processlength(double *valyew, double *divisor, Char *ch,
boolean *lengthIsNegative, char **treestr, long *parens)
{ /* read a branch length from a treestr */
long digit, ordzero, exponent, exponentIsNegative;
boolean pointread, hasExponent;
ordzero = '0';
*lengthIsNegative = false;
pointread = false;
hasExponent = false;
exponentIsNegative = -1; // 3 states: -1 = unassigned, 1 = true, 0 = false
exponent = 0;
*valyew = 0.0;
*divisor = 1.0;
sgetch(ch, parens, treestr);
if ('+' == *ch)
sgetch(ch, parens, treestr); // ignore leading '+', because "+1.2345" == "1.2345"
else if ('-' == *ch)
{
*lengthIsNegative = true;
sgetch(ch, parens, treestr);
}
digit = (long)(*ch - ordzero);
while ( ((digit <= 9) && (digit >= 0)) || '.' == *ch || '-' == *ch
|| '+' == *ch || 'E' == *ch || 'e' == *ch) {
if ('.' == *ch )
{
if (!pointread)
pointread = true;
else
{
printf("\n\nERROR: Branch length found with more than one \'.\' in it.\n\n");
exxit(-1);
}
}
else if ('+' == *ch)
{
if (hasExponent && -1 == exponentIsNegative)
exponentIsNegative = 0; // 3 states: -1 = unassigned, 1 = true, 0 = false
else
{
printf("\n\nERROR: Branch length found with \'+\' in an unexpected place.\n\n");
exxit(-1);
}
}
else if ('-' == *ch)
{
if (hasExponent && -1 == exponentIsNegative)
exponentIsNegative = 1; // 3 states: -1 = unassigned, 1 = true, 0 = false
else
{
printf("\n\nERROR: Branch length found with \'-\' in an unexpected place.\n\n");
exxit(-1);
}
}
else if ('E' == *ch || 'e' == *ch)
{
if (!hasExponent)
hasExponent = true;
else
{
printf("\n\nERROR: Branch length found with more than one \'E\' in it.\n\n");
exxit(-1);
}
}
else {
if (!hasExponent)
{
*valyew = *valyew * 10.0 + digit;
if (pointread)
*divisor *= 10.0;
}
else
exponent = 10*exponent + digit;
}
sgetch(ch, parens, treestr);
digit = (long)(*ch - ordzero);
}
if (hasExponent)
{
if (exponentIsNegative)
*divisor *= pow(10.,(double)exponent);
else
*divisor /= pow(10.,(double)exponent);
}
if (*lengthIsNegative)
*valyew = -(*valyew);
} /* processlength */
void writename(long start, long n, long *enterorder)
{ /* write species name and number in entry order */
long i, j;
for (i = start; i < start+n; i++) {
printf(" %3ld. ", i+1);
for (j = 0; j < nmlngth; j++)
putchar(nayme[enterorder[i] - 1][j]);
putchar('\n');
fflush(stdout);
}
} /* writename */
void memerror()
{
printf("Error allocating memory\n");
exxit(-1);
} /* memerror */
void odd_malloc(long x)
{ /* error message if attempt to malloc too little or too much memory */
printf ("ERROR: a function asked for an inappropriate amount of memory:");
printf (" %ld bytes\n", x);
printf (" This can mean one of two things:\n");
printf (" 1. The input file is incorrect");
printf (" (perhaps it was not saved as Text Only),\n");
printf (" 2. There is a bug in the program.\n");
printf (" Please check your input file carefully.\n");
printf (" If it seems to be a bug, please mail joe (at) gs.washington.edu\n");
printf (" with the name of the program, your computer system type,\n");
printf (" a full description of the problem, and with the input data file.\n");
printf (" (which should be in the body of the message, not as an Attachment).\n");
/* abort() can be used to crash */
exxit(-1);
}
MALLOCRETURN *mymalloc(long x)
{ /* wrapper for malloc, allowing error message if too little, too much */
MALLOCRETURN *new_block;
if ((x <= 0) ||
(x > TOO_MUCH_MEMORY))
odd_malloc(x);
new_block = (MALLOCRETURN *)calloc(1, x);
if (!new_block) {
memerror();
return (MALLOCRETURN *) new_block;
} else
return (MALLOCRETURN *) new_block;
} /* mymalloc */
void gnu(node **grbg, node **p)
{ /* this and the following are do-it-yourself garbage collectors.
Make a new node or pull one off the garbage list */
if (*grbg != NULL) {
*p = *grbg;
*grbg = (*grbg)->next;
} else
*p = (node *)Malloc(sizeof(node));
(*p)->back = NULL;
(*p)->next = NULL;
(*p)->tip = false;
(*p)->times_in_tree = 0.0;
(*p)->r = 0.0;
(*p)->theta = 0.0;
(*p)->x = NULL;
(*p)->protx = NULL; /* for the sake of proml */
} /* gnu */
void chuck(node **grbg, node *p)
{
/* collect garbage on p -- put it on front of garbage list */
p->back = NULL;
p->next = *grbg;
*grbg = p;
} /* chuck */
void zeronumnuc(node *p, long endsite)
{
long i,j;
for (i = 0; i < endsite; i++)
for (j = (long)A; j <= (long)O; j++)
p->numnuc[i][j] = 0;
} /* zeronumnuc */
void zerodiscnumnuc(node *p, long endsite)
{
long i,j;
for (i = 0; i < endsite; i++)
for (j = (long)zero; j <= (long)seven; j++)
p->discnumnuc[i][j] = 0;
} /* zerodiscnumnuc */
void allocnontip(node *p, long *zeros, long endsite)
{ /* allocate an interior node */
/* used by dnacomp, dnapars, & dnapenny */
p->numsteps = (steptr)Malloc(endsite*sizeof(long));
p->oldnumsteps = (steptr)Malloc(endsite*sizeof(long));
p->base = (baseptr)Malloc(endsite*sizeof(long));
p->oldbase = (baseptr)Malloc(endsite*sizeof(long));
p->numnuc = (nucarray *)Malloc(endsite*sizeof(nucarray));
memcpy(p->base, zeros, endsite*sizeof(long));
memcpy(p->numsteps, zeros, endsite*sizeof(long));
memcpy(p->oldbase, zeros, endsite*sizeof(long));
memcpy(p->oldnumsteps, zeros, endsite*sizeof(long));
zeronumnuc(p, endsite);
} /* allocnontip */
void allocdiscnontip(node *p, long *zeros, unsigned char *zeros2, long endsite)
{ /* allocate an interior node */
/* used by pars */
p->numsteps = (steptr)Malloc(endsite*sizeof(long));
p->oldnumsteps = (steptr)Malloc(endsite*sizeof(long));
p->discbase = (discbaseptr)Malloc(endsite*sizeof(unsigned char));
p->olddiscbase = (discbaseptr)Malloc(endsite*sizeof(unsigned char));
p->discnumnuc = (discnucarray *)Malloc(endsite*sizeof(discnucarray));
memcpy(p->discbase, zeros2, endsite*sizeof(unsigned char));
memcpy(p->numsteps, zeros, endsite*sizeof(long));
memcpy(p->olddiscbase, zeros2, endsite*sizeof(unsigned char));
memcpy(p->oldnumsteps, zeros, endsite*sizeof(long));
zerodiscnumnuc(p, endsite);
} /* allocdiscnontip */
void allocnode(node **anode, long *zeros, long endsite)
{ /* allocate a node */
/* used by dnacomp, dnapars, & dnapenny */
*anode = (node *)Malloc(sizeof(node));
allocnontip(*anode, zeros, endsite);
} /* allocnode */
void allocdiscnode(node **anode, long *zeros, unsigned char *zeros2,
long endsite)
{ /* allocate a node */
/* used by pars */
*anode = (node *)Malloc(sizeof(node));
allocdiscnontip(*anode, zeros, zeros2, endsite);
} /* allocdiscnontip */
void gnutreenode(node **grbg, node **p, long i, long endsite, long *zeros)
{ /* this and the following are do-it-yourself garbage collectors.
Make a new node or pull one off the garbage list */
if (*grbg != NULL) {
*p = *grbg;
*grbg = (*grbg)->next;
memcpy((*p)->numsteps, zeros, endsite*sizeof(long));
memcpy((*p)->oldnumsteps, zeros, endsite*sizeof(long));
memcpy((*p)->base, zeros, endsite*sizeof(long));
memcpy((*p)->oldbase, zeros, endsite*sizeof(long));
zeronumnuc(*p, endsite);
} else
allocnode(p, zeros, endsite);
(*p)->back = NULL;
(*p)->next = NULL;
(*p)->tip = false;
(*p)->visited = false;
(*p)->index = i;
(*p)->numdesc = 0;
(*p)->sumsteps = 0.0;
} /* gnutreenode */
void gnudisctreenode(node **grbg, node **p, long i,
long endsite, long *zeros, unsigned char *zeros2)
{ /* this and the following are do-it-yourself garbage collectors.
Make a new node or pull one off the garbage list */
if (*grbg != NULL) {
*p = *grbg;
*grbg = (*grbg)->next;
memcpy((*p)->numsteps, zeros, endsite*sizeof(long));
memcpy((*p)->oldnumsteps, zeros, endsite*sizeof(long));
memcpy((*p)->discbase, zeros2, endsite*sizeof(unsigned char));
memcpy((*p)->olddiscbase, zeros2, endsite*sizeof(unsigned char));
zerodiscnumnuc(*p, endsite);
} else
allocdiscnode(p, zeros, zeros2, endsite);
(*p)->back = NULL;
(*p)->next = NULL;
(*p)->tip = false;
(*p)->visited = false;
(*p)->index = i;
(*p)->numdesc = 0;
(*p)->sumsteps = 0.0;
} /* gnudisctreenode */
void setupnode(node *p, long i)
{ /* initialization of node pointers, variables */
p->next = NULL;
p->back = NULL;
p->times_in_tree = (double) i * 1.0;
p->index = i;
p->tip = false;
} /* setupnode */
node *pnode(tree *t, node *p) {
/* Get the "parent nodelet" of p's node group */
return t->nodep[p->index - 1];
}
long count_sibs (node *p)
{ /* Count the number of nodes in a ring, return the total number of */
/* nodes excluding the one passed into the function (siblings) */
node *q;
long return_int = 0;
if (p->tip) {
printf ("Error: the function count_sibs called on a tip. This is a bug.\n");
exxit (-1);
}
q = p->next;
while (q != p) {
if (q == NULL) {
printf ("Error: a loop of nodes was not closed.\n");
exxit (-1);
} else {
return_int++;
q = q->next;
}
}
return return_int;
} /* count_sibs */
void inittrav (node *p)
{ /* traverse to set pointers uninitialized on inserting */
long i, num_sibs;
node *sib_ptr;
if (p == NULL)
return;
if (p->tip)
return;
num_sibs = count_sibs (p);
sib_ptr = p;
for (i=0; i < num_sibs; i++) {
sib_ptr = sib_ptr->next;
sib_ptr->initialized = false;
inittrav(sib_ptr->back);
}
} /* inittrav */
void commentskipper(char **treestr, long *bracket)
{ /* skip over comment bracket contents in reading tree */
char c;
c = *(*treestr)++;
while (c != ']') {
if(!(**treestr)) {
ajErr("ERROR: Unmatched comment brackets");
exxit(-1);
}
if(c == '[') {
(*bracket)++;
commentskipper(treestr, bracket);
}
c = *(*treestr)++;
}
(*bracket)--;
} /* commentskipper */
long countcomma(char *treestr, long *comma)
{
/* Modified by Dan F. 11/10/96 */
/* countcomma rewritten so it passes back both lparen+comma to allocate nodep
and a pointer to the comma variable. This allows the tree to know how many
species exist, and the tips to be placed in the front of the nodep array */
Char c;
long lparen = 0;
long bracket = 0;
char *treeptr = treestr;
(*comma) = 0;
for (;;){
c = *treeptr++;
if (!c)
break;
if (c == ';')
break;
if (c == ',')
(*comma)++;
if (c == '(')
lparen++;
if (c == '[') {
bracket++;
commentskipper(&treeptr, &bracket);
}
}
return lparen + (*comma);
} /*countcomma*/
long countsemic(char *treestr)
{ /* Used to determine the number of user trees. Return
either a: the number of semicolons in the file outside comments
or b: the first integer in the file */
Char c;
long return_val, semic = 0;
long bracket = 0;
char *treeptr = treestr;
/* Eat all whitespace */
c = *treeptr++;
while ((c == ' ') ||
(c == '\t') ||
(c == '\n')) {
c = *treeptr++;
}
/* Then figure out if the first non-white character is a digit; if
so, return it */
if (isdigit ((int) c)) {
return_val = atoi(&c);
} else {
/* Loop past all characters, count the number of semicolons
outside of comments */
for (;;){
c = *treeptr++;
if (!c)
break;
if (c == ';')
semic++;
if (c == '[') {
bracket++;
commentskipper(&treeptr, &bracket);
}
}
return_val = semic;
}
return return_val;
} /* countsemic */
void hookup(node *p, node *q)
{ /* hook together two nodes */
assert(p != NULL);
assert(q != NULL);
p->back = q;
q->back = p;
} /* hookup */
void unhookup(node *p, node *q)
{
/* unhook two nodes. Not strictly required, but helps check assumptions */
assert(p != NULL);
assert(q != NULL);
assert(p->back != NULL);
assert(q->back != NULL);
assert(p->back == q);
assert(q->back == p);
p->back = NULL;
q->back = NULL;
}
void link_trees(long local_nextnum, long nodenum, long local_nodenum,
pointarray nodep)
{
if(local_nextnum == 0)
hookup(nodep[nodenum], nodep[local_nodenum]);
else if(local_nextnum == 1)
hookup(nodep[nodenum], nodep[local_nodenum]->next);
else if(local_nextnum == 2)
hookup(nodep[nodenum], nodep[local_nodenum]->next->next);
else
printf("Error in Link_trees()");
} /* link_trees() */
void allocate_nodep(pointarray *nodep, char *treestr, long *precalc_tips)
{ /* pre-compute space and allocate memory for nodep */
long numnodes; /* returns number commas & ( */
long numcom = 0; /* returns number commas */
numnodes = countcomma(treestr, &numcom) + 1;
*nodep = (pointarray)Malloc(2*numnodes*sizeof(node *));
(*precalc_tips) = numcom + 1; /* this will be used in placing the
tip nodes in the front region of
nodep. Used for species check? */
} /* allocate_nodep -plc */
void malloc_pheno (node *p, long endsite, long rcategs)
{ /* Allocate the phenotype arrays; used by dnaml */
long i;
p->x = (phenotype)Malloc(endsite*sizeof(ratelike));
p->underflows = (double *)Malloc(endsite * sizeof(double));
for (i = 0; i < endsite; i++)
p->x[i] = (ratelike)Malloc(rcategs*sizeof(sitelike));
} /* malloc_pheno */
void malloc_ppheno (node *p,long endsite, long rcategs)
{
/* Allocate the phenotype arrays; used by proml */
long i;
p->protx = (pphenotype)Malloc(endsite*sizeof(pratelike));
p->underflows = (double *)Malloc(endsite*sizeof(double));
for (i = 0; i < endsite; i++)
p->protx[i] = (pratelike)Malloc(rcategs*sizeof(psitelike));
} /* malloc_ppheno */
long take_name_from_tree (Char *ch, Char *str, char **treestr)
{
/* This loop reads a name from treefile and stores it in *str.
Returns the length of the name string. str must be at
least MAXNCH bytes, but no effort is made to null-terminate
the string. Underscores and newlines are converted to spaces.
Characters beyond MAXNCH are discarded. */
long name_length = 0;
do {
if ((*ch) == '_')
(*ch) = ' ';
if ( name_length < MAXNCH )
str[name_length++] = (*ch);
(*ch) = *(*treestr)++;
if (*ch == '\n')
*ch = ' ';
} while ( strchr(":,)[;", *ch) == NULL );
return name_length;
} /* take_name_from_tree */
void match_names_to_data (Char *str, pointarray treenode, node **p, long spp)
{
/* This loop matches names taken from treestr to indexed names in
the data file */
boolean found;
long i, n;
n = 1;
do {
found = true;
for (i = 0; i < nmlngth; i++) {
found = (found && ((str[i] == nayme[n - 1][i]) ||
(((nayme[n - 1][i] == '_') && (str[i] == ' ')) ||
((nayme[n - 1][i] == ' ') && (str[i] == '\0')))));
}
if (found)
*p = treenode[n - 1];
else
n++;
} while (!(n > spp || found));
if (n > spp) {
printf("\n\nERROR: Cannot find species: ");
for (i = 0; (str[i] != '\0') && (i < MAXNCH); i++)
putchar(str[i]);
printf(" in data file\n\n");
exxit(-1);
}
} /* match_names_to_data */
void addelement(node **p, node *q, Char *ch, long *parens, char **treestr,
pointarray treenode, boolean *goteof, boolean *first, pointarray nodep,
long *nextnode, long *ntips, boolean *haslengths, node **grbg,
initptr initnode, boolean unifok, long maxnodes)
{
/* Recursive procedure adds nodes to user-defined tree
This is the main (new) tree-reading procedure */
node *pfirst;
long i, len = 0, nodei = 0;
boolean notlast;
Char str[MAXNCH+1];
node *r;
long furs = 0;
if ((*ch) == '(') {
(*nextnode)++; /* get ready to use new interior node */
nodei = *nextnode; /* do what needs to be done at bottom */
if ( maxnodes != -1 && nodei > maxnodes) {
printf("ERROR in input tree file: Attempting to allocate too\n");
printf("many nodes. This is usually caused by a unifurcation.\n");
printf("To use this tree with this program use Retree to read\n");
printf("and write this tree.\n");
exxit(-1);
}
/* do what needs to be done at bottom */
(*initnode)(p, grbg, q, len, nodei, ntips,
parens, bottom, treenode, nodep, str, ch, treestr);
pfirst = (*p);
notlast = true;
while (notlast) { /* loop through immediate descendants */
furs++;
(*initnode)(&(*p)->next, grbg, q,
len, nodei, ntips, parens, nonbottom, treenode,
nodep, str, ch, treestr);
/* ... doing what is done before each */
r = (*p)->next;
sgetch(ch, parens, treestr); /* look for next character */
addelement(&(*p)->next->back, (*p)->next, ch, parens, treestr,
treenode, goteof, first, nodep, nextnode, ntips,
haslengths, grbg, initnode, unifok, maxnodes);
(*initnode)(&r, grbg, q, len, nodei, ntips,
parens, hslength, treenode, nodep, str, ch, treestr);
/* do what is done after each about length */
pfirst->numdesc++; /* increment number of descendants */
*p = r; /* make r point back to p */
if ((*ch) == ')') {
notlast = false;
do {
sgetch(ch, parens, treestr);
} while ((*ch) != ',' && (*ch) != ')' &&
(*ch) != '[' && (*ch) != ';' && (*ch) != ':');
}
}
if ( furs <= 1 && !unifok ) {
printf("ERROR in input tree file: A Unifurcation was detetected.\n");
printf("To use this tree with this program use retree to read and");
printf(" write this tree\n");
exxit(-1);
}
(*p)->next = pfirst;
(*p) = pfirst;
} else if ((*ch) != ')') { /* if it's a species name */
for (i = 0; i < MAXNCH+1; i++) /* fill string with nulls */
str[i] = '\0';
len = take_name_from_tree (ch, str, treestr); /* get the name */
if ((*ch) == ')')
(*parens)--; /* decrement count of open parentheses */
(*initnode)(p, grbg, q, len, nodei, ntips,
parens, tip, treenode, nodep, str, ch, treestr);
/* do what needs to be done at a tip */
} else
sgetch(ch, parens, treestr);
if (q != NULL)
hookup(q, (*p)); /* now hook up */
(*initnode)(p, grbg, q, len, nodei, ntips,
parens, iter, treenode, nodep, str, ch, treestr);
/* do what needs to be done to variable iter */
if ((*ch) == ':')
(*initnode)(p, grbg, q, len, nodei, ntips,
parens, length, treenode, nodep, str, ch, treestr);
/* do what needs to be done with length */
else if ((*ch) != ';' && (*ch) != '[')
(*initnode)(p, grbg, q, len, nodei, ntips,
parens, hsnolength, treenode, nodep, str, ch, treestr);
/* ... or what needs to be done when no length */
if ((*ch) == '[')
(*initnode)(p, grbg, q, len, nodei, ntips,
parens, treewt, treenode, nodep, str, ch, treestr);
/* ... for processing a tree weight */
else if ((*ch) == ';') /* ... and at end of tree */
(*initnode)(p, grbg, q, len, nodei, ntips,
parens, unittrwt, treenode, nodep, str, ch, treestr);
} /* addelement */
void treeread (char** treestr, node **root, pointarray treenode,
boolean *goteof, boolean *first, pointarray nodep,
long *nextnode, boolean *haslengths, node **grbg, initptr initnode,
boolean unifok, long maxnodes)
{
/* read in user-defined tree and set it up */
/* Eats everything up to the first open paren, then
* calls the recursive function addelement, which builds the
* tree and calls back to initnode. */
char ch;
long parens = 0;
long ntips = 0;
(*goteof) = false;
(*nextnode) = spp;
if (!**treestr) {
(*goteof) = true;
return;
}
sgetch(&ch, &parens, treestr);
while (ch != '(') {
/* Eat everything in the file (i.e. digits, tabs) until you
encounter an open-paren */
sgetch(&ch, &parens, treestr);
}
if (haslengths != NULL)
(*haslengths) = true;
addelement(root, NULL, &ch, &parens, treestr,
treenode, goteof, first, nodep, nextnode, &ntips,
haslengths, grbg, initnode, unifok, maxnodes);
if (first)
(*first) = false;
if (parens != 0) {
printf("\n\nERROR in tree file: unmatched parentheses\n\n");
exxit(-1);
}
} /* treeread */
void addelement2(node *q, Char *ch, long *parens, char **treestr,
pointarray treenode, boolean lngths, double *trweight, boolean *goteof,
long *nextnode, long *ntips, long no_species, boolean *haslengths,
boolean unifok, long maxnodes)
{
/* recursive procedure adds nodes to user-defined tree
-- old-style bifurcating-only version */
node *pfirst = NULL, *p;
long i, len, current_loop_index;
boolean notlast, minusread;
Char str[MAXNCH];
double valyew, divisor;
long furs = 0;
if ((*ch) == '(') {
current_loop_index = (*nextnode) + spp;
(*nextnode)++;
if ( maxnodes != -1 && current_loop_index > maxnodes) {
printf("ERROR in intree file: Attempting to allocate too many nodes\n");
printf("This is usually caused by a unifurcation. To use this\n");
printf("intree with this program use retree to read and write\n");
printf("this tree.\n");
exxit(-1);
}
/* This is an assignment of an interior node */
p = treenode[current_loop_index];
pfirst = p;
notlast = true;
while (notlast) {
furs++;
/* This while loop goes through a circle (triad for
bifurcations) of nodes */
p = p->next;
/* added to ensure that non base nodes in loops have indices */
p->index = current_loop_index + 1;
sgetch(ch, parens, treestr);
addelement2(p, ch, parens, treestr, treenode, lngths, trweight,
goteof, nextnode, ntips, no_species, haslengths, unifok, maxnodes);
if ((*ch) == ')') {
notlast = false;
do {
sgetch(ch, parens, treestr);
} while ((*ch) != ',' && (*ch) != ')' &&
(*ch) != '[' && (*ch) != ';' && (*ch) != ':');
}
}
if ( furs <= 1 && !unifok ) {
printf("ERROR in intree file: A Unifurcation was detected.\n");
printf("To use this intree with this program use retree to read and");
printf(" write this tree\n");
exxit(-1);
}
} else if ((*ch) != ')') {
for (i = 0; i < MAXNCH; i++)
str[i] = '\0';
len = take_name_from_tree (ch, str, treestr);
match_names_to_data (str, treenode, &p, spp);
pfirst = p;
if ((*ch) == ')')
(*parens)--;
(*ntips)++;
strncpy (p->nayme, str, len);
} else
sgetch(ch, parens, treestr);
if ((*ch) == '[') { /* getting tree weight from last comment field */
if (**treestr) {
*trweight = strtod(*treestr, treestr);
if(trweight) {
sgetch(ch, parens, treestr);
if (*ch != ']') {
ajErr("ERROR: Missing right square bracket");
exxit(-1);
}
else {
sgetch(ch, parens, treestr);
if (*ch != ';') {
ajErr("ERROR: Missing semicolon after square brackets");
exxit(-1);
}
}
}
else {
ajErr("ERROR: Expecting tree weight in last comment field");
exxit(-1);
}
}
}
else if ((*ch) == ';') {
(*trweight) = 1.0 ;
/* the ajWarn should be for multiple trees as input */
/* ajWarn("WARNING: tree weight set to 1.0");*/
}
else if (haslengths != NULL)
(*haslengths) = ((*haslengths) && q == NULL);
if (q != NULL)
hookup(q, pfirst);
if ((*ch) == ':') {
processlength(&valyew, &divisor, ch,
&minusread, treestr, parens);
printf("processlength valyew:%f divisor:%f q: %p\n", valyew, divisor, q);
if (q != NULL) {
if (!minusread)
q->oldlen = valyew / divisor;
else
q->oldlen = 0.0;
if (lngths) {
q->v = valyew / divisor;
q->back->v = q->v;
q->iter = false;
q->back->iter = false;
}
}
}
} /* addelement2 */
void treeread2 (char **treestr, node **root, pointarray treenode,
boolean lngths, double *trweight, boolean *goteof,
boolean *haslengths, long *no_species, boolean unifok, long maxnodes)
{
/* read in user-defined tree and set it up
-- old-style bifurcating-only version */
char ch;
long parens = 0;
long ntips = 0;
long nextnode;
(*goteof) = false;
nextnode = 0;
if (!**treestr) {
(*goteof) = true;
return;
}
sgetch(&ch, &parens, treestr);
while (ch != '(') {
/* Eat everything in the file (i.e. digits, tabs) until you
encounter an open-paren */
sgetch(&ch, &parens, treestr);
}
addelement2(NULL, &ch, &parens, treestr, treenode, lngths, trweight,
goteof, &nextnode, &ntips, (*no_species), haslengths,
unifok, maxnodes);
(*root) = treenode[*no_species];
(*root)->oldlen = 0.0;
if (parens != 0) {
ajErr("ERROR in tree file: unmatched parentheses");
exxit(-1);
}
} /* treeread2 */
void exxit(int exitcode)
{
#ifdef WIN32
if (exitcode == 0)
#endif
if (exitcode == 0)
ajExit();
else
ajExitBad();
#ifdef WIN32
else {
puts ("Hit Enter or Return to close program.");
puts(" You may have to hit Enter or Return twice.");
getchar ();
getchar ();
phyRestoreConsoleAttributes();
exit (exitcode);
}
#endif
} /* exxit */
void unroot(tree *t, long nonodes)
{
/* used by fitch, restml and contml */
if (t->start->back == NULL) {
if (t->start->next->back->tip)
t->start = t->start->next->next->back;
else t->start = t->start->next->back;
}
if (t->start->next->back == NULL) {
if (t->start->back->tip)
t->start = t->start->next->next->back;
else t->start = t->start->back;
}
if (t->start->next->next->back == NULL) {
if (t->start->back->tip)
t->start = t->start->next->back;
else t->start = t->start->back;
}
unroot_r(t->start,t->nodep,nonodes);
unroot_r(t->start->back, t->nodep, nonodes);
}
void unroot_here(node* root, node** nodep, long nonodes)
{
node* tmpnode;
double newl;
/* used by unroot */
/* assumes bifurcation this is ok in the programs that use it */
newl = root->next->oldlen + root->next->next->oldlen;
root->next->back->oldlen = newl;
root->next->next->back->oldlen = newl;
newl = root->next->v + root->next->next->v;
root->next->back->v = newl;
root->next->next->back->v = newl;
root->next->back->back=root->next->next->back;
root->next->next->back->back = root->next->back;
while ( root->index != nonodes ) {
tmpnode = nodep[ root->index ];
nodep[root->index] = root;
root->index++;
root->next->index++;
root->next->next->index++;
nodep[root->index - 2] = tmpnode;
tmpnode->index--;
tmpnode->next->index--;
tmpnode->next->next->index--;
}
}
void unroot_r(node* p, node** nodep, long nonodes)
{
/* used by unroot */
node *q;
if ( p->tip) return;
q = p->next;
while ( q != p ) {
if (q->back == NULL)
unroot_here(q, nodep, nonodes);
else unroot_r(q->back, nodep, nonodes);
q = q->next;
}
}
void clear_connections(tree *t, long nonodes)
{
long i;
node *p;
for ( i = 0 ; i < nonodes ; i++) {
p = t->nodep[i];
if (p != NULL) {
p->back = NULL;
p->v = 0;
for (p = p->next; p && p != t->nodep[i]; p = p->next) {
p->next->back = NULL;
p->next->v = 0;
}
}
}
}
#ifdef WIN32
void phySaveConsoleAttributes()
{
if ( GetConsoleScreenBufferInfo(hConsoleOutput, &savecsbi) )
savecsbi_valid = true;
} /* PhySaveConsoleAttributes */
void phySetConsoleAttributes()
{
hConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE);
if ( hConsoleOutput == INVALID_HANDLE_VALUE )
hConsoleOutput = NULL;
if ( hConsoleOutput != NULL ) {
phySaveConsoleAttributes();
SetConsoleTextAttribute(hConsoleOutput,
BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_INTENSITY);
}
} /* phySetConsoleAttributes */
void phyRestoreConsoleAttributes()
{
COORD coordScreen = { 0, 0 };
DWORD cCharsWritten;
DWORD dwConSize;
printf("Press enter to quit.\n");
fflush(stdout);
getchar();
if ( savecsbi_valid ) {
dwConSize = savecsbi.dwSize.X * savecsbi.dwSize.Y;
SetConsoleTextAttribute(hConsoleOutput, savecsbi.wAttributes);
FillConsoleOutputAttribute( hConsoleOutput, savecsbi.wAttributes,
dwConSize, coordScreen, &cCharsWritten );
}
} /* phyRestoreConsoleAttributes */
void phyFillScreenColor()
{
COORD coordScreen = { 0, 0 };
DWORD cCharsWritten;
CONSOLE_SCREEN_BUFFER_INFO csbi; /* to get buffer info */
DWORD dwConSize;
if ( GetConsoleScreenBufferInfo( hConsoleOutput, &csbi ) ) {
dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
FillConsoleOutputAttribute( hConsoleOutput, csbi.wAttributes,
dwConSize, coordScreen, &cCharsWritten );
}
} /* PhyFillScreenColor */
void phyClearScreen()
{
COORD coordScreen = { 0, 0 }; /* here's where we'll home the
cursor */
DWORD cCharsWritten;
CONSOLE_SCREEN_BUFFER_INFO csbi; /* to get buffer info */
DWORD dwConSize; /* number of character cells in
the current buffer */
/* get the number of character cells in the current buffer */
GetConsoleScreenBufferInfo( hConsoleOutput, &csbi );
dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
/* fill the entire screen with blanks */
FillConsoleOutputCharacter( hConsoleOutput, (TCHAR) ' ',
dwConSize, coordScreen, &cCharsWritten );
/* get the current text attribute */
GetConsoleScreenBufferInfo( hConsoleOutput, &csbi );
/* now set the buffer's attributes accordingly */
FillConsoleOutputAttribute( hConsoleOutput, csbi.wAttributes,
dwConSize, coordScreen, &cCharsWritten );
/* put the cursor at (0, 0) */
SetConsoleCursorPosition( hConsoleOutput, coordScreen );
return;
} /* PhyClearScreen */
#endif /* WIN32 */
/* These functions are temporarily used for translating the fixed-width
* space-padded nayme array to an array of null-terminated char *. */
char **stringnames_new(void)
{
/* Copy nayme array to null terminated strings and return array of char *.
* Spaces are stripped from end of naym's.
* Returned array size is spp+1; last element is NULL. */
char **names;
char *ch;
long /*len,*/ i;
names = (char **)Malloc((spp+1) * sizeof(char *));
for ( i = 0; i < spp; i++ ) {
/*len = strlen(nayme[i]);*/
names[i] = (char *)Malloc((MAXNCH+1) * sizeof(char));
strncpy(names[i], nayme[i], MAXNCH);
names[i][MAXNCH] = '\0';
/* Strip trailing spaces */
for ( ch = names[i] + MAXNCH - 1; *ch == ' ' || *ch == '\0'; ch-- )
*ch = '\0';
}
names[spp] = NULL;
return names;
}
void stringnames_delete(char **names)
{
/* Free a string array returned by stringnames_new() */
long i;
assert( names != NULL );
for ( i = 0; i < spp; i++ ) {
assert( names[i] != NULL );
free(names[i]);
}
free(names);
}
int fieldwidth_double(double val, unsigned int precision)
{
/* Printf a double to a temporary buffer with specified precision using %g
* and return its length. Precision must not be greater than 999,999 */
char format[10];
char buf[0x200]; /* TODO: What's the largest possible? */
if (precision > 999999)
abort();
sprintf(format, "%%.%uf", precision); /* %.Nf */
/* snprintf() would be better, but is it avaliable on all systems? */
return sprintf(buf, format, val);
}
void output_matrix_d(FILE *fp, double **matrix,
unsigned long rows, unsigned long cols,
char **row_head, char **col_head, int flags)
{
/*
* Print a matrix of double to file. Headings are given in row_head and
* col_head, either of which may be NULL to indicate that headings should not
* be printed. Otherwise, they must be null-terminated arrays of pointers to
* null-terminalted character arrays.
*
* The macro OUTPUT_PRECISION defines the number of significant figures to
* print, and OUTPUT_TEXTWIDTH defines the maximum length of each line.
*
* Optional formatting is specified by flags argument, using macros MAT_*
* defined in phylip.h.
*/
unsigned *colwidth; /* [0..spp-1] min width of each column */
unsigned headwidth; /* min width of row header column */
unsigned long linelen; /* length of current printed line */
unsigned fw;
unsigned long row, col;
unsigned long i;
unsigned long cstart, cend;
unsigned long textwidth = OUTPUT_TEXTWIDTH;
const unsigned int gutter = 1;
boolean do_block;
boolean lower_triangle;
boolean border;
boolean output_cols;
boolean pad_row_head;
if ( flags & MAT_NOHEAD )
col_head = NULL;
if ( flags & MAT_NOBREAK )
textwidth = 0;
do_block = (flags & MAT_BLOCK) && (textwidth > 0);
lower_triangle = flags & MAT_LOWER;
border = flags & MAT_BORDER;
output_cols = flags & MAT_PCOLS;
pad_row_head = flags & MAT_PADHEAD;
/* Determine minimal width for row headers, if given */
headwidth = 0;
if ( row_head != NULL ) {
for (row = 0; row < rows; row++) {
fw = strlen(row_head[row]);
if ( headwidth < fw )
headwidth = fw;
}
}
/* Enforce minimum of 10 ch for machine-readable output */
if ( (pad_row_head) && (headwidth < 10) )
headwidth = 10;
/* Determine minimal width for each matrix col */
colwidth = (unsigned int *)Malloc(spp * sizeof(int));
for (col = 0; col < cols; col++) {
if ( col_head != NULL )
colwidth[col] = strlen(col_head[col]);
else
colwidth[col] = 0;
for (row = 0; row < rows; row++) {
fw = fieldwidth_double(matrix[row][col], PRECISION);
if ( colwidth[col] < fw )
colwidth[col] = fw;
}
}
/*** Print the matrix ***/
/* Number of columns if requested */
if ( output_cols ) {
fprintf(fp, "%5lu\n", cols);
}
/* Omit last column for lower triangle */
if ( lower_triangle )
cols--;
/* Blocks */
cstart = cend = 0;
while ( cend != cols ) {
if ( do_block ) {
linelen = headwidth;
for ( col = cstart; col < cols; col++ ) {
if ( linelen + colwidth[col] + gutter > textwidth ) {
break;
}
linelen += colwidth[col] + gutter;
}
cend = col;
/* Always print at least one, regardless of line len */
if ( cend == cstart )
cend++;
} else {
cend = cols;
}
/* Column headers */
if ( col_head != NULL ) {
/* corner space */
for ( i = 0; i < headwidth; i++ )
putc(' ', fp);
if ( border ) {
for ( i = 0; i < gutter+1; i++ )
putc(' ', fp);
}
/* Names */
for ( col = cstart; col < cend; col++ ) {
for ( i = 0; i < gutter; i++ )
putc(' ', fp);
/* right justify */
fw = strlen(col_head[col]);
for ( i = 0; i < colwidth[col] - fw; i++ )
putc(' ', fp);
fputs(col_head[col], fp);
}
putc('\n', fp);
}
/* Top border */
if ( border ) {
for ( i = 0; i < headwidth + gutter; i++ )
putc(' ', fp);
putc('\\', fp);
for ( col = cstart; col < cend; col++ ) {
for ( i = 0; i < colwidth[col] + gutter; i++ )
putc('-', fp);
}
putc('\n', fp);
}
/* Rows */
for (row = 0; row < rows; row++) {
/* Row header, if given */
if ( row_head != NULL ) {
/* right-justify for non-machine-readable */
if ( !pad_row_head ) {
for ( i = strlen(row_head[row]); i < headwidth; i++ )
putc(' ', fp);
}
fputs(row_head[row], fp);
/* left-justify for machine-readable */
if ( pad_row_head ) {
for ( i = strlen(row_head[row]); i < headwidth; i++ )
putc(' ', fp);
}
}
linelen = headwidth;
/* Left border */
if ( border ) {
for ( i = 0; i < gutter; i++ )
putc(' ', fp);
putc('|', fp);
linelen += 2;
}
/* Row data */
for (col = cstart; col < cend; col++) { /* cols */
/* Stop after col == row for lower triangle */
if ( lower_triangle && col >= row )
break;
/* Break line if going over max text width */
if ( !do_block && textwidth > 0 ) {
if ( linelen + colwidth[col] > textwidth ) {
putc('\n', fp);
linelen = 0;
}
linelen += colwidth[col] + gutter;
}
for ( i = 0; i < gutter; i++ )
putc(' ', fp);
/* Print the datum */
fprintf(fp, "%*.6f", colwidth[col], matrix[row][col]);
}
putc('\n', fp);
} /* End of row */
if (col_head != NULL)
putc('\n', fp); /* blank line */
cstart = cend;
} /* End of block */
free(colwidth);
} /* output_matrix_d */
void emboss_printtree(node *p, char* title)
{
int i;
int ilen;
node* root = p;
printf("\n%s\n", title);
ilen = strlen(title);
for (i=0;i < ilen; i++)
printf("=");
printf("\n");
emboss_printtreenode(p, root);
return;
}
static void emboss_printtreenode(node *p, node* root)
{
int i;
node* q;
static int margin=0;
char name[256];
int ended = false;
double x;
char spaces[256];
for(i=0;itip) /* named node */
{
strncpy(name, nayme[p->index - 1], nmlngth);
for (i=nmlngth;i;i--)
{
if (name[i-1] == ' ')
{
name[i-1] = '_';
}
else
{
if (!ended)
{
name[i] = '\0';
ended = true;
}
}
}
printf("'%s'\n", name);
if (p->index)
printf("%s : index:%ld\n",spaces, p->index);
if (p->tip)
printf("%s : tip:%s\n", spaces, (p->tip ? "true" : "false"));
if (p->initialized)
printf("%s : initialized:%s\n",
spaces, (p->initialized ? "true" : "false"));
if (p->visited)
printf("%s : visited:%s\n",
spaces, (p->visited ? "true" : "false"));
if (p->numdesc)
printf("%s : numdesc:%ld\n",spaces, p->numdesc);
if (p->times_in_tree)
printf("%s : times_in_tree:%f\n",spaces, p->times_in_tree);
if (p->sumsteps)
printf("%s : sumsteps:%f\n",spaces, p->sumsteps);
printf("\n");
}
else /* link to next nodes - loop until we get back here */
{
printf("(\n");
/* numdesc: number of immediate descendants */
if (p->index)
printf("%s : index:%ld\n",spaces, p->index);
if (p->tip)
printf("%s : tip:%s\n", spaces, (p->tip ? "true" : "false"));
if (p->initialized)
printf("%s : initialized:%s\n",
spaces, (p->initialized ? "true" : "false"));
if (p->visited)
printf("%s : visited:%s\n",
spaces, (p->visited ? "true" : "false"));
if (p->numdesc)
printf("%s : numdesc:%ld\n",spaces, p->numdesc);
if (p->times_in_tree)
printf("%s : times_in_tree:%f\n",spaces, p->times_in_tree);
if (p->sumsteps)
printf("%s : sumsteps:%f\n",spaces, p->sumsteps);
printf("\n");
margin += 2;
q=p->next;
while (q != p) {
emboss_printtreenode(q->back, root);
q = q->next;
if (q == p)
break;
printf("%s ,\n\n",spaces);
}
margin -= 2;
printf("%s)\n", spaces);
}
if (p != root)
{
x = p->v;
printf("%s+ len:%.5f\n\n", spaces, x);
return;
}
printf(";\n\n");
margin = 0;
}
PHYLIPNEW-3.69.650/src/dollop.c 0000664 0001750 0001750 00000062007 11305225544 012520 0000000 0000000
#include "phylip.h"
#include "disc.h"
#include "dollo.h"
/* version 3.6. (c) Copyright 1993-2004 by the University of Washington.
Written by Joseph Felsenstein, Akiko Fuseki, Sean Lamont, and Andrew Keeffe.
Permission is granted to copy and use this program provided no fee is
charged for it and provided that this copyright notice is not removed. */
#define maxtrees 100 /* maximum number of tied trees stored */
AjPPhyloState* phylostates = NULL;
AjPPhyloProp phyloanc = NULL;
AjPPhyloProp phyloweights = NULL;
AjPPhyloTree* phylotrees = NULL;
#ifndef OLDC
/* function prototypes */
//void getoptions(void);
void allocrest(void);
void doinit(void);
void inputoptions(void);
void doinput(void);
void dollop_count(node *, steptr, steptr);
void preorder(node *, steptr, steptr, long, boolean, long, bitptr, pointptr);
void evaluate(node *);
void savetree(void);
void dollop_addtree(long *);
void tryadd(node *, node **, node **);
void addpreorder(node *, node *, node *);
void tryrearr(node *, node **, boolean *);
void repreorder(node *, node **, boolean *);
void rearrange(node **);
void describe(void);
void initdollopnode(node **, node **, node *, long, long, long *,
long *, initops, pointarray, pointarray, Char *, Char *, char **);
void maketree(void);
void reallocchars(void);
void emboss_getoptions(char *pgm, int argc, char *argv[]);
/* function prototypes */
#endif
Char infilename[FNMLNGTH], intreename[FNMLNGTH];
Char weightfilename[FNMLNGTH], ancfilename[FNMLNGTH];
const char* outfilename;
const char* outtreename;
AjPFile embossoutfile;
AjPFile embossouttree;
node *root;
long col, msets, ith, j, l, njumble, jumb, numtrees;
long inseed, inseed0;
boolean jumble, usertree, weights, ancvar, questions, dollo,
trout, progress, treeprint, stepbox, ancseq, mulsets,
firstset, justwts;
boolean *ancone, *anczero, *ancone0, *anczero0;
pointptr treenode; /* pointers to all nodes in tree */
double threshold;
double *threshwt;
longer seed;
long *enterorder;
double **fsteps;
steptr numsteps;
bestelm *bestrees;
Char *guess;
gbit *garbage;
char *progname;
/* Variables for treeread */
boolean goteof, firsttree, haslengths, phirst;
pointarray nodep;
node *grbg;
long *zeros;
/* Local variables for maketree, propagated globally for C version: */
long minwhich;
double like, bestyet, bestlike, bstlike2, minsteps;
boolean lastrearr;
double nsteps[maxuser];
node *there;
long fullset;
long shimotrees;
bitptr zeroanc, oneanc;
long *place;
Char ch;
boolean *names;
steptr numsone, numszero;
bitptr steps;
void emboss_getoptions(char *pgm, int argc, char *argv[])
{
ajint numseqs=0;
ajint numwts=0;
AjPStr method = NULL;
ancvar = false;
dollo = true;
jumble = false;
njumble = 1;
trout = true;
usertree = false;
goteof = false;
weights = false;
justwts = false;
printdata = false;
progress = true;
treeprint = true;
stepbox = false;
ancseq = false;
mulsets = false;
msets = 1;
embInitPV(pgm, argc, argv, "PHYLIPNEW",VERSION);
phylostates = ajAcdGetDiscretestates("infile");
while (phylostates[numseqs])
numseqs++;
phylotrees = ajAcdGetTree("intreefile");
if (phylotrees)
{
numtrees = 0;
while (phylotrees[numtrees])
numtrees++;
usertree = true;
}
phyloweights = ajAcdGetProperties("weights");
if (phyloweights)
{
weights = true;
numwts = ajPhyloPropGetSize(phyloweights);
}
if (numseqs > 1) {
mulsets = true;
msets = numseqs;
}
else if (numwts > 1) {
mulsets = true;
msets = numwts;
justwts = true;
}
method = ajAcdGetListSingle("method");
if(ajStrMatchC(method, "d")) dollo = true;
else dollo = false;
if(!usertree) {
njumble = ajAcdGetInt("njumble");
if(njumble >0) {
inseed = ajAcdGetInt("seed");
jumble = true;
emboss_initseed(inseed, &inseed0, seed);
}
else njumble = 1;
}
if((mulsets) && (!jumble)) {
jumble = true;
inseed = ajAcdGetInt("seed");
emboss_initseed(inseed, &inseed0, seed);
}
phyloanc = ajAcdGetProperties("ancfile");
if(phyloanc) ancvar = true;
threshold = ajAcdGetFloat("threshold");
printdata = ajAcdGetBoolean("printdata");
progress = ajAcdGetBoolean("progress");
treeprint = ajAcdGetBoolean("treeprint");
trout = ajAcdGetToggle("trout");
stepbox = ajAcdGetBoolean("stepbox");
ancseq = ajAcdGetBoolean("ancseq");
embossoutfile = ajAcdGetOutfile("outfile");
emboss_openfile(embossoutfile, &outfile, &outfilename);
if(trout) {
embossouttree = ajAcdGetOutfile("outtreefile");
emboss_openfile(embossouttree, &outtree, &outtreename);
}
printf("\nDollo and polymorphism parsimony algorithm, version %s\n\n", VERSION);
fprintf(outfile,"\nDollo and polymorphism parsimony algorithm,");
fprintf(outfile," version %s\n\n",VERSION);
} /* emboss_getoptions */
void reallocchars(void)
{
long i;
free(extras);
free(weight);
free(threshwt);
free(numsteps);
free(ancone);
free(anczero);
free(ancone0);
free(anczero0);
free(numsone);
free(numszero);
free(guess);
if (usertree) {
for (i = 1; i <= maxuser; i++){
free(fsteps);
fsteps[i - 1] = (double *)Malloc(chars*sizeof(double));
}
}
extras = (steptr)Malloc(chars*sizeof(long));
weight = (steptr)Malloc(chars*sizeof(long));
threshwt = (double *)Malloc(chars*sizeof(double));
numsteps = (steptr)Malloc(chars*sizeof(long));
ancone = (boolean *)Malloc(chars*sizeof(boolean));
anczero = (boolean *)Malloc(chars*sizeof(boolean));
ancone0 = (boolean *)Malloc(chars*sizeof(boolean));
anczero0 = (boolean *)Malloc(chars*sizeof(boolean));
numsone = (steptr)Malloc(chars*sizeof(long));
numszero = (steptr)Malloc(chars*sizeof(long));
guess = (Char *)Malloc(chars*sizeof(Char));
}
void allocrest(void)
{
long i;
extras = (steptr)Malloc(chars*sizeof(long));
weight = (steptr)Malloc(chars*sizeof(long));
threshwt = (double *)Malloc(chars*sizeof(double));
if (usertree) {
fsteps = (double **)Malloc(maxuser*sizeof(double *));
for (i = 1; i <= maxuser; i++)
fsteps[i - 1] = (double *)Malloc(chars*sizeof(double));
}
bestrees = (bestelm *) Malloc(maxtrees*sizeof(bestelm));
for (i = 1; i <= maxtrees; i++)
bestrees[i - 1].btree = (long *)Malloc(nonodes*sizeof(long));
numsteps = (steptr)Malloc(chars*sizeof(long));
nayme = (naym *)Malloc(spp*sizeof(naym));
enterorder = (long *)Malloc(spp*sizeof(long));
place = (long *)Malloc(nonodes*sizeof(long));
ancone = (boolean *)Malloc(chars*sizeof(boolean));
anczero = (boolean *)Malloc(chars*sizeof(boolean));
ancone0 = (boolean *)Malloc(chars*sizeof(boolean));
anczero0 = (boolean *)Malloc(chars*sizeof(boolean));
numsone = (steptr)Malloc(chars*sizeof(long));
numszero = (steptr)Malloc(chars*sizeof(long));
guess = (Char *)Malloc(chars*sizeof(Char));
zeroanc = (bitptr)Malloc(words*sizeof(long));
oneanc = (bitptr)Malloc(words*sizeof(long));
steps = (bitptr)Malloc(words*sizeof(long));
} /* allocrest */
void doinit(void)
{
/* initializes variables */
inputnumbersstate(phylostates[0], &spp, &chars, &nonodes, 1);
words = chars / bits + 1;
// if (printdata)
// fprintf(outfile, "%2ld species, %3ld characters\n\n", spp, chars);
alloctree(&treenode);
setuptree(treenode);
allocrest();
} /* doinit */
void inputoptions(void)
{
/* input the information on the options */
long i;
if(justwts){
if(firstset){
if (ancvar) {
inputancestorsstr(phyloanc->Str[0], anczero0, ancone0);
}
}
for (i = 0; i < (chars); i++)
weight[i] = 1;
inputweightsstr(phyloweights->Str[0], chars, weight, &weights);
}
else {
if (!firstset) {
samenumspstate(phylostates[ith-1], &chars, ith);
reallocchars();
}
for (i = 0; i < (chars); i++)
weight[i] = 1;
if (ancvar)
inputancestorsstr(phyloanc->Str[0], anczero0, ancone0);
if (weights)
inputweightsstr(phyloweights->Str[ith-1], chars, weight, &weights);
}
if ((weights || justwts) && printdata)
printweights(outfile, 0, chars, weight, "Characters");
for (i = 0; i < (chars); i++) {
if (!ancvar) {
anczero[i] = true;
ancone[i] = false;
} else {
anczero[i] = anczero0[i];
ancone[i] = ancone0[i];
}
}
if (ancvar && printdata)
printancestors(outfile, anczero, ancone);
questions = false;
for (i = 0; i < (chars); i++) {
questions = (questions || (ancone[i] && anczero[i]));
threshwt[i] = threshold * weight[i];
}
} /* inputoptions */
void doinput(void)
{
/* reads the input data */
inputoptions();
if(!justwts || firstset)
disc_inputdata(phylostates[ith-1], treenode, dollo, printdata, outfile);
} /* doinput */
void dollop_count(node *p, steptr numsone, steptr numszero)
{
/* counts the number of steps in a fork of the tree.
The program spends much of its time in this PROCEDURE */
long i, j, l;
if (dollo) {
for (i = 0; i < (words); i++)
steps[i] = (treenode[p->back->index - 1]->stateone[i] &
p->statezero[i] & zeroanc[i]) |
(treenode[p->back->index - 1]->statezero[i] & p->stateone[i] &
fullset & (~zeroanc[i]));
} else {
for (i = 0; i < (words); i++)
steps[i] = treenode[p->back->index - 1]->stateone[i] &
treenode[p->back->index - 1]->statezero[i] & p->stateone[i] &
p->statezero[i];
}
j = 1;
l = 0;
for (i = 0; i < (chars); i++) {
l++;
if (l > bits) {
l = 1;
j++;
}
if (((1L << l) & steps[j - 1]) != 0) {
assert(j <= words); /* checking array indexing */
if (((1L << l) & zeroanc[j - 1]) != 0)
numszero[i] += weight[i];
else
numsone[i] += weight[i];
}
}
} /* dollop_count */
void preorder(node *p, steptr numsone, steptr numszero, long words,
boolean dollo, long fullset, bitptr zeroanc, pointptr treenode)
{
/* go back up tree setting up and counting interior node
states */
if (!p->tip) {
correct(p, fullset, dollo, zeroanc, treenode);
preorder(p->next->back, numsone,numszero, words, dollo, fullset,
zeroanc, treenode);
preorder(p->next->next->back, numsone,numszero, words, dollo, fullset,
zeroanc, treenode);
}
if (p->back != NULL)
dollop_count(p, numsone,numszero);
} /* preorder */
void evaluate(node *r)
{
/* Determines the number of losses or polymorphisms needed
for a tree. This is the minimum number needed to evolve
chars on this tree */
long i, stepnum, smaller;
double sum, term;
sum = 0.0;
for (i = 0; i < (chars); i++) {
numszero[i] = 0;
numsone[i] = 0;
}
for (i = 0; i < (words); i++)
zeroanc[i] = fullset;
postorder(r);
preorder(r, numsone, numszero, words, dollo, fullset, zeroanc, treenode);
for (i = 0; i < (words); i++)
zeroanc[i] = 0;
postorder(r);
preorder(r, numsone, numszero, words, dollo, fullset, zeroanc, treenode);
for (i = 0; i < (chars); i++) {
smaller = spp * weight[i];
numsteps[i] = smaller;
if (anczero[i]) {
numsteps[i] = numszero[i];
smaller = numszero[i];
}
if (ancone[i] && numsone[i] < smaller)
numsteps[i] = numsone[i];
stepnum = numsteps[i] + extras[i];
if (stepnum <= threshwt[i])
term = stepnum;
else
term = threshwt[i];
sum += term;
if (usertree && which <= maxuser)
fsteps[which - 1][i] = term;
guess[i] = '?';
if (!ancone[i] || (anczero[i] && numszero[i] < numsone[i]))
guess[i] = '0';
else if (!anczero[i] || (ancone[i] && numsone[i] < numszero[i]))
guess[i] = '1';
}
if (usertree && which <= maxuser) {
nsteps[which - 1] = sum;
if (which == 1) {
minwhich = 1;
minsteps = sum;
} else if (sum < minsteps) {
minwhich = which;
minsteps = sum;
}
}
like = -sum;
} /* evaluate */
void savetree()
{
/* record in place where each species has to be
added to reconstruct this tree */
long i, j;
node *p;
boolean done;
for (i = 0; i < (nonodes); i++)
place[i] = 0;
place[root->index - 1] = 1;
for (i = 1; i <= (spp); i++) {
p = treenode[i - 1];
while (place[p->index - 1] == 0) {
place[p->index - 1] = i;
p = p->back;
if (p != NULL)
p = treenode[p->index - 1];
}
if (i > 1) {
place[i - 1] = place[p->index - 1];
j = place[p->index - 1];
done = false;
while (!done) {
place[p->index - 1] = spp + i - 1;
p = treenode[p->index - 1];
p = p->back;
done = (p == NULL);
if (!done)
done = (place[p->index - 1] != j);
}
}
}
} /* savetree */
void dollop_addtree(long *pos)
{
/*puts tree from ARRAY place in its proper position
in ARRAY bestrees */
long i;
for (i =nextree - 1; i >= (*pos); i--) {
memcpy(bestrees[i].btree, bestrees[i - 1].btree, spp*sizeof(long));
bestrees[i].gloreange = bestrees[i - 1].gloreange;
bestrees[i].locreange = bestrees[i - 1].locreange;
bestrees[i].collapse = bestrees[i - 1].collapse;
}
for (i = 0; i < (spp); i++)
bestrees[(*pos) - 1].btree[i] = place[i];
nextree++;
} /* dollop_addtree */
void tryadd(node *p, node **item, node **nufork)
{
/* temporarily adds one fork and one tip to the tree.
if the location where they are added yields greater
"likelihood" than other locations tested up to that
time, then keeps that location as there */
long pos;
boolean found;
add(p, *item, *nufork, &root, treenode);
evaluate(root);
if (lastrearr) {
if (like >= bstlike2) {
savetree();
if (like > bstlike2) {
bestlike = bstlike2 = like;
pos = 1;
nextree = 1;
dollop_addtree(&pos);
} else {
pos = 0;
findtree(&found, &pos, nextree, place, bestrees);
/* findtree calls for a bestelm* but is getting */
/* a long**, LM */
if (!found) {
if (nextree <= maxtrees)
dollop_addtree(&pos);
}
}
}
}
if (like > bestyet) {
bestyet = like;
there = p;
}
re_move(item, nufork, &root, treenode);
} /* tryadd */
void addpreorder(node *p, node *item_, node *nufork_)
{
/* traverses a binary tree, calling PROCEDURE tryadd
at a node before calling tryadd at its descendants */
node *item= item_;
node *nufork = nufork_;
if (p == NULL)
return;
tryadd(p, &item,&nufork);
if (!p->tip) {
addpreorder(p->next->back, item, nufork);
addpreorder(p->next->next->back, item, nufork);
}
} /* addpreorder */
void tryrearr(node *p, node **r, boolean *success)
{
/* evaluates one rearrangement of the tree.
if the new tree has greater "likelihood" than the old
one sets success := TRUE and keeps the new tree.
otherwise, restores the old tree */
node *frombelow, *whereto, *forknode;
double oldlike;
if (p->back == NULL)
return;
forknode = treenode[p->back->index - 1];
if (forknode->back == NULL)
return;
oldlike = bestyet;
if (p->back->next->next == forknode)
frombelow = forknode->next->next->back;
else
frombelow = forknode->next->back;
whereto = forknode->back;
re_move(&p, &forknode, &root, treenode);
add(whereto, p, forknode, &root, treenode);
evaluate(*r);
if (oldlike - like < LIKE_EPSILON) {
re_move(&p, &forknode, &root, treenode);
add(frombelow, p, forknode, &root, treenode);
} else {
(*success) = true;
bestyet = like;
}
} /* tryrearr */
void repreorder(node *p, node **r, boolean *success)
{
/* traverses a binary tree, calling PROCEDURE tryrearr
at a node before calling tryrearr at its descendants */
if (p == NULL)
return;
tryrearr(p, r,success);
if (!p->tip) {
repreorder(p->next->back, r,success);
repreorder(p->next->next->back, r,success);
}
} /* repreorder */
void rearrange(node **r_)
{
/* traverses the tree (preorder), finding any local
rearrangement which decreases the number of steps.
if traversal succeeds in increasing the tree's
"likelihood", PROCEDURE rearrange runs traversal again */
node **r = r_;
boolean success = true;
while (success) {
success = false;
repreorder(*r, r,&success);
}
} /* rearrange */
void describe()
{
/* prints ancestors, steps and table of numbers of steps in
each character */
if (treeprint)
fprintf(outfile, "\nrequires a total of %10.3f\n", -like);
if (stepbox) {
putc('\n', outfile);
writesteps(weights, dollo, numsteps);
}
if (questions)
guesstates(guess);
if (ancseq) {
hypstates(fullset, dollo, guess, treenode, root, garbage, zeroanc, oneanc);
putc('\n', outfile);
}
putc('\n', outfile);
if (trout) {
col = 0;
treeout(root, nextree, &col, root);
}
} /* describe */
void initdollopnode(node **p, node **grbg, node *q, long len, long nodei,
long *ntips, long *parens, initops whichinit,
pointarray treenode, pointarray nodep, Char *str, Char *ch,
char **treestr)
{
/* initializes a node */
/* LM 7/27 I added this function and the commented lines around */
/* treeread() to get the program running, but all 4 move programs*/
/* are improperly integrated into the v4.0 support files. As is */
/* this is a patchwork function */
boolean minusread;
double valyew, divisor;
switch (whichinit) {
case bottom:
gnutreenode(grbg, p, nodei, chars, zeros);
treenode[nodei - 1] = *p;
break;
case nonbottom:
gnutreenode(grbg, p, nodei, chars, zeros);
break;
case tip:
match_names_to_data (str, treenode, p, spp);
break;
case length: /* if there is a length, read it and discard value */
processlength(&valyew, &divisor, ch, &minusread, treestr, parens);
break;
default: /*cases hslength,hsnolength,treewt,unittrwt,iter,*/
break;
}
} /* initdollopnode */
void maketree()
{
/* constructs a binary tree from the pointers in treenode.
adds each node at location which yields highest "likelihood"
then rearranges the tree for greatest "likelihood" */
long i, j, nextnode;
double gotlike;
node *item, *nufork, *dummy, *p;
char *treestr;
fullset = (1L << (bits + 1)) - (1L << 1);
if (!usertree) {
for (i = 1; i <= (spp); i++)
enterorder[i - 1] = i;
if (jumble)
randumize(seed, enterorder);
root = treenode[enterorder[0] - 1];
add(treenode[enterorder[0] - 1], treenode[enterorder[1] - 1],
treenode[spp], &root, treenode);
if (progress) {
printf("Adding species:\n");
writename(0, 2, enterorder);
#ifdef WIN32
phyFillScreenColor();
#endif
}
lastrearr = false;
for (i = 3; i <= (spp); i++) {
bestyet = -350.0 * spp * chars;
item = treenode[enterorder[i - 1] - 1];
nufork = treenode[spp + i - 2];
addpreorder(root, item, nufork);
add(there, item, nufork, &root, treenode);
like = bestyet;
rearrange(&root);
if (progress) {
writename(i - 1, 1, enterorder);
#ifdef WIN32
phyFillScreenColor();
#endif
}
lastrearr = (i == spp);
if (lastrearr) {
if (progress) {
printf("\nDoing global rearrangements\n");
printf(" !");
for (j = 1; j <= (nonodes); j++)
if ( j % (( nonodes / 72 ) + 1 ) == 0 )
putchar('-');
printf("!\n");
#ifdef WIN32
phyFillScreenColor();
#endif
}
bestlike = bestyet;
if (jumb == 1) {
bstlike2 = bestlike;
nextree = 1;
}
do {
if (progress)
printf(" ");
gotlike = bestlike;
for (j = 0; j < (nonodes); j++) {
bestyet = - 350.0 * spp * chars;
item = treenode[j];
if (item != root) {
nufork = treenode[j]->back;
re_move(&item, &nufork, &root, treenode);
there = root;
addpreorder(root, item, nufork);
add(there, item, nufork, &root, treenode);
}
if (progress) {
if ( j % (( nonodes / 72 ) + 1 ) == 0 )
putchar('.');
fflush(stdout);
}
}
if (progress) {
putchar('\n');
#ifdef WIN32
phyFillScreenColor();
#endif
}
} while (bestlike > gotlike);
}
}
if (progress)
putchar('\n');
for (i = spp - 1; i >= 1; i--)
re_move(&treenode[i], &dummy, &root, treenode);
if (jumb == njumble) {
if (treeprint) {
putc('\n', outfile);
if (nextree == 2)
fprintf(outfile, "One most parsimonious tree found:\n");
else
fprintf(outfile, "%6ld trees in all found\n", nextree - 1);
}
if (nextree > maxtrees + 1) {
if (treeprint)
fprintf(outfile, "here are the first%4ld of them\n", (long)maxtrees);
nextree = maxtrees + 1;
}
if (treeprint)
putc('\n', outfile);
for (i = 0; i <= (nextree - 2); i++) {
root = treenode[0];
add(treenode[0], treenode[1], treenode[spp], &root, treenode);
for (j = 3; j <= spp; j++) {
add(treenode[bestrees[i].btree[j - 1] - 1], treenode[j - 1],
treenode[spp + j - 2], &root, treenode);}
evaluate(root);
printree(1.0, treeprint, root);
describe();
for (j = 1; j < (spp); j++)
re_move(&treenode[j], &dummy, &root, treenode);
}
}
} else {
if (numtrees > 2) {
emboss_initseed(inseed, &inseed0, seed);
printf("\n");
}
if (treeprint) {
fprintf(outfile, "User-defined tree");
if (numtrees > 1)
putc('s', outfile);
fprintf(outfile, ":\n");
}
names = (boolean *)Malloc(spp*sizeof(boolean));
which = 1;
firsttree = true; /**/
nodep = NULL; /**/
nextnode = 0; /**/
haslengths = 0; /**/
phirst = 0; /**/
zeros = (long *)Malloc(chars*sizeof(long)); /**/
for (i = 0; i < chars; i++) /**/
zeros[i] = 0; /**/
while (which <= numtrees) {
treestr = ajStrGetuniquePtr(&phylotrees[which-1]->Tree);
treeread(&treestr, &root, treenode, &goteof, &firsttree,
nodep, &nextnode, &haslengths,
&grbg, initdollopnode,false,nonodes);
for (i = spp; i < (nonodes); i++) {
p = treenode[i];
for (j = 1; j <= 3; j++) {
p->stateone = (bitptr)Malloc(words*sizeof(long));
p->statezero = (bitptr)Malloc(words*sizeof(long));
p = p->next;
}
} /* debug: see comment at initdollopnode() */
if (treeprint)
fprintf(outfile, "\n\n");
evaluate(root);
printree(1.0, treeprint, root);
describe();
which++;
}
FClose(intree);
fprintf(outfile, "\n\n");
if (numtrees > 1 && chars > 1)
standev(numtrees, minwhich, minsteps, nsteps, fsteps, seed);
free(names);
}
if (jumb == njumble) {
if (progress) {
printf("Output written to file \"%s\"\n\n", outfilename);
if (trout)
printf("Trees also written onto file \"%s\"\n\n", outtreename);
}
if (ancseq)
freegarbage(&garbage);
}
} /* maketree */
int main(int argc, Char *argv[])
{ /* Dollo or polymorphism parsimony by uphill search */
#ifdef MAC
argc = 1; /* macsetup("Dollop",""); */
argv[0] = "Dollop";
#endif
init(argc, argv);
emboss_getoptions("fdollop", argc, argv);
/* reads in spp, chars, and the data. Then calls maketree to
construct the tree */
progname = argv[0];
ibmpc = IBMCRT;
ansi = ANSICRT;
garbage = NULL;
firstset = true;
bits = 8*sizeof(long) - 1;
doinit();
if (dollo)
fprintf(outfile, "Dollo");
else
fprintf(outfile, "Polymorphism");
fprintf(outfile, " parsimony method\n\n");
if (printdata && justwts)
fprintf(outfile, "%2ld species, %3ld characters\n\n", spp, chars);
for (ith = 1; ith <= (msets); ith++) {
if (msets > 1 && !justwts) {
fprintf(outfile, "Data set # %ld:\n\n",ith);
if (progress)
printf("\nData set # %ld:\n",ith);
}
if (justwts){
fprintf(outfile, "Weights set # %ld:\n\n", ith);
if (progress)
printf("\nWeights set # %ld:\n\n", ith);
}
if (printdata && !justwts)
fprintf(outfile, "%2ld species, %3ld characters\n\n", spp, chars);
doinput();
if (ith == 1)
firstset = false;
for (jumb = 1; jumb <= njumble; jumb++)
maketree();
}
/* this would be an appropriate place to deallocate memory, including these items:
*/
free(steps);
FClose(infile);
FClose(outfile);
FClose(outtree);
#ifdef MAC
fixmacfile(outfilename);
fixmacfile(outtreename);
#endif
#ifdef WIN32
phyRestoreConsoleAttributes();
#endif
embExit();
return 0;
} /* Dollo or polymorphism parsimony by uphill search */
PHYLIPNEW-3.69.650/src/dist.c 0000664 0001750 0001750 00000026405 11253743724 012203 0000000 0000000 #include "phylip.h"
#include "dist.h"
/* version 3.6. (c) Copyright 1993-2004 by the University of Washington.
Written by Joseph Felsenstein, Akiko Fuseki, Sean Lamont, and Andrew Keeffe.
Permission is granted to copy and use this program provided no fee is
charged for it and provided that this copyright notice is not removed. */
void alloctree(pointptr *treenode, long nonodes)
{
/* allocate spp tips and (nonodes - spp) forks, each containing three
* nodes. Fill in treenode where 0..spp-1 are pointers to tip nodes, and
* spp..nonodes-1 are pointers to one node in each fork. */
/* used in fitch, kitsch, neighbor */
long i, j;
node *p, *q;
*treenode = (pointptr)Malloc(nonodes*sizeof(node *));
for (i = 0; i < spp; i++)
(*treenode)[i] = (node *)Malloc(sizeof(node));
for (i = spp; i < nonodes; i++) {
q = NULL;
for (j = 1; j <= 3; j++) {
p = (node *)Malloc(sizeof(node));
p->next = q;
q = p;
}
p->next->next->next = p;
(*treenode)[i] = p;
}
} /* alloctree */
void freetree(pointptr *treenode, long nonodes)
{
long i;
node *p, *q;
for (i = 0; i < spp; i++)
free((*treenode)[i]);
for (i = spp; i < nonodes; i++) {
p = (*treenode)[i];
q = p->next;
while(q != p)
{
node * r = q;
q = q->next;
free(r);
}
free(p);
}
free(*treenode);
} /* freetree */
void allocd(long nonodes, pointptr treenode)
{
/* used in fitch & kitsch */
long i, j;
node *p;
for (i = 0; i < (spp); i++) {
treenode[i]->d = (vector)Malloc(nonodes*sizeof(double));
}
for (i = spp; i < nonodes; i++) {
p = treenode[i];
for (j = 1; j <= 3; j++) {
p->d = (vector)Malloc(nonodes*sizeof(double));
p = p->next;
}
}
}
void freed(long nonodes, pointptr treenode)
{
/* used in fitch */
long i, j;
node *p;
for (i = 0; i < (spp); i++) {
free(treenode[i]->d);
}
for (i = spp; i < nonodes; i++) {
p = treenode[i];
for (j = 1; j <= 3; j++) {
free(p->d);
p = p->next;
}
}
}
void allocw(long nonodes, pointptr treenode)
{
/* used in fitch & kitsch */
long i, j;
node *p;
for (i = 0; i < (spp); i++) {
treenode[i]->w = (vector)Malloc(nonodes*sizeof(double));
}
for (i = spp; i < nonodes; i++) {
p = treenode[i];
for (j = 1; j <= 3; j++) {
p->w = (vector)Malloc(nonodes*sizeof(double));
p = p->next;
}
}
}
void freew(long nonodes, pointptr treenode)
{
/* used in fitch */
long i, j;
node *p;
for (i = 0; i < (spp); i++) {
free(treenode[i]->w);
}
for (i = spp; i < nonodes; i++) {
p = treenode[i];
for (j = 1; j <= 3; j++) {
free(p->w);
p = p->next;
}
}
}
void setuptree(tree *a, long nonodes)
{
/* initialize a tree */
/* used in fitch, kitsch, & neighbor */
long i=0;
node *p;
for (i = 1; i <= nonodes; i++) {
a->nodep[i - 1]->back = NULL;
a->nodep[i - 1]->tip = (i <= spp);
a->nodep[i - 1]->iter = true;
a->nodep[i - 1]->index = i;
a->nodep[i - 1]->t = 0.0;
a->nodep[i - 1]->sametime = false;
a->nodep[i - 1]->v = 0.0;
if (i > spp) {
p = a->nodep[i-1]->next;
while (p != a->nodep[i-1]) {
p->back = NULL;
p->tip = false;
p->iter = true;
p->index = i;
p->t = 0.0;
p->sametime = false;
p = p->next;
}
}
}
a->likelihood = -1.0;
a->start = a->nodep[0];
a->root = NULL;
} /* setuptree */
void dist_inputdata(AjPPhyloDist dist,
boolean replicates, boolean printdata, boolean lower,
boolean upper, vector *x, intvector *reps)
{
/* read in distance matrix */
/* used in fitch & neighbor */
long i=0, j=0, k=0, columns=0;
ajint ipos;
if (replicates)
columns = 4;
else
columns = 6;
if (printdata) {
fprintf(outfile, "\nName Distances");
if (replicates)
fprintf(outfile, " (replicates)");
fprintf(outfile, "\n---- ---------");
if (replicates)
fprintf(outfile, "-------------");
fprintf(outfile, "\n\n");
}
ipos = 0;
for (i = 0; i < spp; i++) {
x[i][i] = 0.0;
initnamedist(dist,i);
for (j = 0; j < spp; j++) {
x[i][j] = dist->Data[ipos];
reps[i][j] = dist->Replicates[ipos++];
}
}
if (!printdata)
return;
for (i = 0; i < spp; i++) {
for (j = 0; j < nmlngth; j++)
putc(nayme[i][j], outfile);
putc(' ', outfile);
for (j = 1; j <= spp; j++) {
fprintf(outfile, "%10.5f", x[i][j - 1]);
if (replicates || !replicates)
fprintf(outfile, " (%3ld)", reps[i][j - 1]);
if (j % columns == 0 && j < spp) {
putc('\n', outfile);
for (k = 1; k <= nmlngth + 1; k++)
putc(' ', outfile);
}
}
putc('\n', outfile);
}
putc('\n', outfile);
} /* inputdata */
void coordinates(node *p, double lengthsum, long *tipy, double *tipmax,
node *start, boolean njoin)
{
/* establishes coordinates of nodes */
node *q, *first, *last;
if (p->tip) {
p->xcoord = (long)(over * lengthsum + 0.5);
p->ycoord = *tipy;
p->ymin = *tipy;
p->ymax = *tipy;
(*tipy) += down;
if (lengthsum > *tipmax)
*tipmax = lengthsum;
return;
}
q = p->next;
do {
if (q->back)
coordinates(q->back, lengthsum + q->v, tipy,tipmax, start, njoin);
q = q->next;
} while ((p == start || p != q) && (p != start || p->next != q));
first = p->next->back;
q = p;
while (q->next != p && q->next->back) /* is this right ? */
q = q->next;
last = q->back;
p->xcoord = (long)(over * lengthsum + 0.5);
if (p == start && p->back)
p->ycoord = p->next->next->back->ycoord;
else
p->ycoord = (first->ycoord + last->ycoord) / 2;
p->ymin = first->ymin;
p->ymax = last->ymax;
} /* coordinates */
void drawline(long i, double scale, node *start, boolean rooted)
{
/* draws one row of the tree diagram by moving up tree */
node *p, *q;
long n=0, j=0;
boolean extra=false, trif=false;
node *r, *first =NULL, *last =NULL;
boolean done=false;
p = start;
q = start;
extra = false;
trif = false;
if (i == (long)p->ycoord && p == start) { /* display the root */
if (rooted) {
if (p->index - spp >= 10)
fprintf(outfile, "-");
else
fprintf(outfile, "--");
}
else {
if (p->index - spp >= 10)
fprintf(outfile, " ");
else
fprintf(outfile, " ");
}
if (p->index - spp >= 10)
fprintf(outfile, "%2ld", p->index - spp);
else
fprintf(outfile, "%ld", p->index - spp);
extra = true;
trif = true;
} else
fprintf(outfile, " ");
do {
if (!p->tip) { /* internal nodes */
r = p->next;
/* r->back here is going to the same node. */
do {
if (!r->back) {
r = r->next;
continue;
}
if (i >= r->back->ymin && i <= r->back->ymax) {
q = r->back;
break;
}
r = r->next;
} while (!((p != start && r == p) || (p == start && r == p->next)));
first = p->next->back;
r = p;
while (r->next != p)
r = r->next;
last = r->back;
if (!rooted && (p == start))
last = p->back;
} /* end internal node case... */
/* draw the line: */
done = (p->tip || p == q);
n = (long)(scale * (q->xcoord - p->xcoord) + 0.5);
if (!q->tip) {
if ((n < 3) && (q->index - spp >= 10))
n = 3;
if ((n < 2) && (q->index - spp < 10))
n = 2;
}
if (extra) {
n--;
extra = false;
}
if ((long)q->ycoord == i && !done) {
if (p->ycoord != q->ycoord)
putc('+', outfile);
if (trif) {
n++;
trif = false;
}
if (!q->tip) {
for (j = 1; j <= n - 2; j++)
putc('-', outfile);
if (q->index - spp >= 10)
fprintf(outfile, "%2ld", q->index - spp);
else
fprintf(outfile, "-%ld", q->index - spp);
extra = true;
} else {
for (j = 1; j < n; j++)
putc('-', outfile);
}
} else if (!p->tip) {
if ((long)last->ycoord > i && (long)first->ycoord < i
&& i != (long)p->ycoord) {
putc('!', outfile);
for (j = 1; j < n; j++)
putc(' ', outfile);
} else {
for (j = 1; j <= n; j++)
putc(' ', outfile);
trif = false;
}
}
if (q != p)
p = q;
} while (!done);
if ((long)p->ycoord == i && p->tip) {
for (j = 0; j < nmlngth; j++)
putc(nayme[p->index - 1][j], outfile);
}
putc('\n', outfile);
} /* drawline */
void printree(node *start, boolean treeprint,
boolean njoin, boolean rooted)
{
/* prints out diagram of the tree */
/* used in fitch & neighbor */
long i;
long tipy;
double scale,tipmax;
if (!treeprint)
return;
putc('\n', outfile);
tipy = 1;
tipmax = 0.0;
coordinates(start, 0.0, &tipy, &tipmax, start, njoin);
scale = 1.0 / (long)(tipmax + 1.000);
for (i = 1; i <= (tipy - down); i++)
drawline(i, scale, start, rooted);
putc('\n', outfile);
} /* printree */
void treeoutr(node *p, long *col, tree *curtree)
{
/* write out file with representation of final tree.
* Rooted case. Used in kitsch and neighbor. */
long i, n, w;
Char c;
double x;
if (p->tip) {
n = 0;
for (i = 1; i <= nmlngth; i++) {
if (nayme[p->index - 1][i - 1] != ' ')
n = i;
}
for (i = 0; i < n; i++) {
c = nayme[p->index - 1][i];
if (c == ' ')
c = '_';
putc(c, outtree);
}
(*col) += n;
} else {
putc('(', outtree);
(*col)++;
treeoutr(p->next->back,col,curtree);
putc(',', outtree);
(*col)++;
if ((*col) > 55) {
putc('\n', outtree);
(*col) = 0;
}
treeoutr(p->next->next->back,col,curtree);
putc(')', outtree);
(*col)++;
}
x = p->v;
if (x > 0.0)
w = (long)(0.43429448222 * log(x));
else if (x == 0.0)
w = 0;
else
w = (long)(0.43429448222 * log(-x)) + 1;
if (w < 0)
w = 0;
if (p == curtree->root)
fprintf(outtree, ";\n");
else {
fprintf(outtree, ":%*.5f", (int)(w + 7), x);
(*col) += w + 8;
}
} /* treeoutr */
void treeout(node *p, long *col, double m, boolean njoin, node *start)
{
/* write out file with representation of final tree */
/* used in fitch & neighbor */
long i=0, n=0, w=0;
Char c;
double x=0.0;
if (p->tip) {
n = 0;
for (i = 1; i <= nmlngth; i++) {
if (nayme[p->index - 1][i - 1] != ' ')
n = i;
}
for (i = 0; i < n; i++) {
c = nayme[p->index - 1][i];
if (c == ' ')
c = '_';
putc(c, outtree);
}
*col += n;
} else {
putc('(', outtree);
(*col)++;
treeout(p->next->back, col, m, njoin, start);
putc(',', outtree);
(*col)++;
if (*col > 55) {
putc('\n', outtree);
*col = 0;
}
treeout(p->next->next->back, col, m, njoin, start);
if (p == start && njoin) {
putc(',', outtree);
treeout(p->back, col, m, njoin, start);
}
putc(')', outtree);
(*col)++;
}
x = p->v;
if (x > 0.0)
w = (long)(m * log(x));
else if (x == 0.0)
w = 0;
else
w = (long)(m * log(-x)) + 1;
if (w < 0)
w = 0;
if (p == start)
fprintf(outtree, ";\n");
else {
fprintf(outtree, ":%*.5f", (int) w + 7, x);
*col += w + 8;
}
} /* treeout */
PHYLIPNEW-3.69.650/src/mlclock.c 0000664 0001750 0001750 00000033607 11253743724 012666 0000000 0000000 /* PHYLIP version 3.6. (c) Copyright 1986-2007 by the University of
* Washington and by Joseph Felsenstein. Written by Joseph
* Felsenstein. Permission is granted to copy and use this program
* provided no fee is charged for it and provided that this copyright
* notice is not removed. */
#include "phylip.h"
#include "seq.h"
#include "mlclock.h"
/* Define the minimum branch length to be enforced for clocklike trees */
const double MIN_BRANCH_LENGTH = 1e-6;
/* MIN_ROOT_TYME is added to the current root tyme and used as the lower
* bound when optimizing at the root. */
const double MIN_ROOT_TYME = -10;
static evaluator_t evaluate = NULL;
static tree *curtree = NULL; /* current tree in use */
static node *current_node = NULL; /* current node being optimized */
static double cur_node_eval(double x);
static double evaluate_tyme(tree *t, node *p, double tyme);
void
mlclock_init(tree *t, evaluator_t f)
{
curtree = t;
evaluate = f;
}
boolean
all_tymes_valid(node *p, double minlength, boolean fix)
{
/* Ensures that all node tymes at node p and descending from it are
* valid, with all branches being not less than minlength. If any
* inconsistencies are found, returns true. If 'fix' is given,
* adjustments are made to make the subtree consistent. Otherwise if
* assertions are enabled, all inconsistencies are fatal. No effort is
* made to check that the parent node tyme p->back->tyme is less than
* p->tyme. */
node *q;
double max_tyme;
boolean ret = true;
/* All tips should have tyme == 0.0 */
if ( p->tip ) {
if ( p->tyme == 0.0 )
return true;
else { /* this would be very bad. */
if ( fix )
p->tyme = 0.0;
else
assert( p->tyme == 0 );
return false;
}
}
for ( q = p->next; q != p; q = q->next ) {
/* All nodes in ring should have same tyme */
if ( q && q->tyme != p->tyme ) {
if ( fix )
q->tyme = p->tyme;
else
assert( q->tyme == p->tyme );
ret = false;
}
/* All subtrees should be OK too */
if (!q->back)
continue;
if ( all_tymes_valid(q->back, minlength, fix) == false )
ret = false;
}
/* Tymes cannot be greater than the minimum child time, less
* branch length */
max_tyme = min_child_tyme(p) - minlength;
if ( p->tyme > max_tyme ) {
if ( fix )
setnodetymes(p, max_tyme);
else
assert( p->tyme < max_tyme );
return false;
}
return ret;
}
void
setnodetymes(node* p, double newtyme)
{ /* Set node tyme for an entire fork. Also clears initialized flags on this
* fork, but not recursively. inittrav() must be called before evaluating
* elsewhere. */
node * q;
curtree->likelihood = UNDEFINED;
p->tyme = newtyme;
p->initialized = false;
if ( p->tip ) return;
for ( q = p->next; q != p; q = q->next ) {
assert(q);
q->tyme = newtyme;
q->initialized = false;
}
} /* setnodetymes */
double
min_child_tyme(node *p)
{
/* Return the minimum tyme of all children. p must be a parent nodelet */
double min;
node *q;
min = 1.0; /* Tymes are always nonpositive */
for ( q = p->next; q != p; q = q->next ) {
if ( q->back == NULL ) continue;
if ( q->back->tyme < min )
min = q->back->tyme;
}
return min;
} /* min_child_tyme */
double
parent_tyme(node *p)
{
/* Return the tyme of the parent of node p. p must be a parent nodelet. */
if ( p->back ) {
return p->back->tyme;
} else {
return p->tyme + MIN_ROOT_TYME;
}
} /* parent_tyme */
boolean
valid_tyme(node *p, double tyme)
{
/* Return true if tyme is a valid tyme to assign to node p. tyme must be
* finite, not greater than any of p's children, and not less than p's
* parent. Also, tip nodes can only be assigned 0. Otherwise false is
* returned. */
/* p must be the parent nodelet of its node group. */
assert( p->tip != true || tyme == 0.0 );
assert( tyme <= min_child_tyme(p) );
assert( tyme >= parent_tyme(p) );
return true;
} /* valid_tyme */
static long
node_max_depth(tree *t, node *p)
{
/* Return the largest number of branches between node p and any tip node. */
long max_depth = 0;
long cdep;
node *q;
assert(p = pnode(t, p));
if (p->tip)
return 0;
for (q = p->next; q != p; q = q->next) {
cdep = node_max_depth(t, q->back) + 1;
if (cdep > max_depth)
max_depth = cdep;
}
return max_depth;
}
static double
node_max_tyme(tree *t, node *p)
{
/* Return the absolute maximum tyme a node can be pushed to. */
return -node_max_depth(t, p) * MIN_BRANCH_LENGTH;
}
void
save_tymes(tree* save_tree, double tymes[])
{
/* Save the current node tymes of save_tree in tymes[]. tymes must point to
* an array of (nonodes - spp) elements. Tyme for node i gets saved in
* tymes[i-spp]. */
int i;
assert( all_tymes_valid(curtree->root, 0.0, false) );
for ( i = spp ; i < nonodes ; i++) {
tymes[i - spp] = save_tree->nodep[i]->tyme;
}
}
void
restore_tymes(tree *load_tree, double tymes[])
{
/* Restore the tymes saved in tymes[] to tree load_tree. See save_tymes()
* */
int i;
for ( i = spp ; i < nonodes ; i++) {
if (load_tree->nodep[i]->tyme != tymes[i-spp])
setnodetymes(load_tree->nodep[i], tymes[i-spp]);
}
/* Check for invalid tymes */
assert( all_tymes_valid(curtree->root, 0.0, false) );
}
static void
push_tymes_to_root(tree *t, node *p, double tyme)
{
/* Set tyme for node p to tyme. Ancestors of p are moved down if necessary to prevent
* negative branch lengths. */
node *q, *r;
assert(p = pnode(t, p));
setnodetymes(p, tyme);
r = p;
while (r->back != NULL) {
q = pnode(t, r->back); /* q = parent(r); */
if (q->tyme > r->tyme - MIN_BRANCH_LENGTH)
setnodetymes(q, r->tyme - MIN_BRANCH_LENGTH);
else
break;
r = q;
}
}
static void
push_tymes_to_tips(tree *t, node *p, double tyme)
{
/* Set tyme for node p to tyme. Descendants of p are moved up if necessary to
* prevent negative branch lengths. */
node *q;
assert( p == pnode(t, p) );
setnodetymes(p, tyme);
for (q = p->next; q != p; q = q->next) {
if (q->back->tyme < p->tyme + MIN_BRANCH_LENGTH) {
if (q->back->tip && q->back->tyme < p->tyme) {
fprintf(stderr,
"Error: Attempt to move node past tips.\n"
"%s line %d\n", __FILE__, __LINE__);
exxit(-1);
}
else {
if(!( q->back->tip ) ) {
push_tymes_to_tips(t, q->back, p->tyme + MIN_BRANCH_LENGTH);
}
}
}
}
}
static void
set_tyme(tree *t, node *p, double tyme)
{
/* Set the tyme for node p, pushing others out of the way */
/* Use rootward node in fork */
p = pnode(t, p);
/* Set node tyme and push other nodes out of the way */
if (tyme < p->tyme)
push_tymes_to_root(t, p, tyme);
else
push_tymes_to_tips(t, p, tyme);
}
static double
evaluate_tyme(tree *t, node *p, double tyme)
{
/* Evaluate curtree if node p is at tyme. Return the score. Leaves original
* tymes intact. */
static double *savetymes = NULL;
static long savetymes_sz = 0;
long nforks = nonodes - spp;
double score = 1.0;
if (savetymes_sz < nforks + 1) {
if (savetymes != NULL)
free(savetymes);
savetymes_sz = nforks;
savetymes = (double *)Malloc(savetymes_sz * sizeof(double));
}
/* Save the current tymes */
save_tymes(t, savetymes);
set_tyme(t, p, tyme);
/* Evaluate the tree */
score = evaluate(p);
/* Restore original tymes */
restore_tymes(t, savetymes);
assert( all_tymes_valid(curtree->root, 0.0, false) );
return score;
}
static double
cur_node_eval(double x)
{
return evaluate_tyme(curtree, current_node, x);
}
double
maximize(double min_tyme, double cur, double max_tyme, double(*f)(double),
double eps, boolean *success)
{
/* Find the maximum of function f by parabolic interpolation and golden section search.
* (based on Brent method in NR) */
/* [min_tyme, max_tyme] is the domain, cur is the best guess and must be
* within the domain, eps is the fractional accuracy of the result, i.e. the
* returned value x will be accurate to +/- x*eps. */
boolean bracket = false;
static long max_iterations = 100; /* maximum iterations */
long it; /* iteration counter */
double x[3], lnl[3]; /* tyme (x) and log likelihood
(lnl) points below, at, and
above the current tyme */
double xn, yn; /* New point */
double d; /* delta x to new point */
double mid; /* Midpoint of (x[0], x[2]) */
double xmax, lnlmax;
double tdelta; /* uphill step for bracket
finding */
double last_d = 0.0;
double prec; /* epsilon * tyme */
double t1, t2, t3, t4; /* temps for parabolic fit */
/* Bracket our maximum; We will assume that we are already close and move
* uphill by exponentially increasing steps until we find a smaller value.
* The initial step should be small to allow us to finish quickly if we're
* still on the maximum from previous smoothings */
x[1] = cur;
tdelta = fabs(10.0 * cur * eps);
x[0] = cur - tdelta;
if (x[0] < min_tyme)
x[0] = min_tyme;
lnl[1] = (*f)(x[1]);
lnl[0] = (*f)(x[0]);
if (lnl[0] < lnl[1]) {
do {
x[2] = x[1] + tdelta;
if (x[2] > max_tyme)
x[2] = max_tyme;
lnl[2] = (*f)(x[2]);
if (lnl[2] < lnl[1])
break;
x[0] = x[1]; lnl[0] = lnl[1];
x[1] = x[2]; lnl[1] = lnl[2];
tdelta *= 2;
} while (x[2] < max_tyme);
}
else { /* lnl[0] > lnl[1] */
/* shift points (0, 1) -> (1, 2) */
x[2] = x[1]; x[1] = x[0];
lnl[2] = lnl[1]; lnl[1] = lnl[0];
do {
x[0] = x[1] - tdelta;
if (x[0] < min_tyme)
x[0] = min_tyme;
lnl[0] = (*f)(x[0]);
if (lnl[0] < lnl[1])
break;
x[2] = x[1]; lnl[2] = lnl[1];
x[1] = x[0]; lnl[1] = lnl[0];
tdelta *= 2;
} while (x[0] > min_tyme);
}
/* FIXME: this should not be necessary. Somewhere we fail to enforce
* MIN_BRANCH_LENGTH */
if ( x[1] < x[0] || x[2] < x[1] ) {
x[1] = (x[2] + x[0]) / 2.0;
lnl[1] = (*f)(x[1]);
}
assert(x[0] <= x[1] && x[1] <= x[2]);
xmax = x[1];
lnlmax = lnl[1];
if (lnl[0] > lnlmax) {
xmax = x[0];
lnlmax = lnl[0];
}
if (lnl[2] > lnlmax) {
xmax = x[2];
lnlmax = lnl[2];
}
bracket = false;
for (it = 0; it < max_iterations; it++) {
assert(x[0] <= x[1] && x[1] <= x[2]);
prec = fabs(x[1] * eps) + 1e-7;
if (x[2] - x[0] < 4.0*prec)
break;
d = 0.0;
mid = (x[2] + x[0]) / 2.0;
if (lnl[0] < lnl[1] && lnl[1] > lnl[0]) {
/* We have a bracket */
bracket = true;
/* Try parabolic interpolation */
t1 = (x[1] - x[0]) * (lnl[1] - lnl[2]);
t2 = (x[1] - x[2]) * (lnl[1] - lnl[0]);
t3 = t1*(x[1] - x[0]) - t2*(x[1] - x[2]);
t4 = 2.0*(t1 - t2);
if (t4 > 0.0)
t3 = -t3;
t4 = fabs(t4);
if ( fabs(t3) < fabs(0.5*t4*last_d)
&& t3 > t4 * (x[0] - x[1])
&& t3 < t4 * (x[2] - x[1]) )
{
d = t3 / t4;
xn = x[1] + d;
/* Keep the new point from getting too close to the end points */
if (xn - x[0] < 2.0*prec || x[2] - xn < 2.0*prec)
d = xn - mid > 0 ? -prec : prec;
}
} else {
/* We should never lose our bracket once we've found it. */
assert( !bracket );
}
if (d == 0.0) {
/* Bisect larger interval using golden ratio */
d = x[1] > mid ? 0.38 * (x[0] - x[1])
: 0.38 * (x[2] - x[1]);
}
/* Keep the new point from getting too close to the middle one */
if (fabs(d) < prec)
d = d > 0 ? prec : -prec;
xn = x[1] + d;
last_d = d;
yn = (*f)(xn);
if (yn > lnlmax) {
*success = true;
xmax = xn;
lnlmax = yn;
}
if (yn > lnl[1]) {
/* (xn, yn) is the new middle point */
if (xn > x[1])
x[0] = x[1];
else
x[2] = x[1];
x[1] = xn; lnl[1] = yn;
}
else {
/* xn is the new bound */
if (xn > x[1])
x[2] = xn;
else
x[0] = xn;
}
}
return xmax;
}
boolean
makenewv(node *p)
{
/* Try to improve tree by moving node p. Returns true if a better likelihood
* was found */
double min_tyme, max_tyme; /* absolute tyme limits */
double new_tyme; /* result from maximize() */
boolean success = false; /* return value */
node *s = curtree->nodep[p->index - 1];
assert( valid_tyme(s, s->tyme) );
/* Tyme cannot be less than parent */
if (s == curtree->root)
min_tyme = s->tyme + MIN_ROOT_TYME;
else
min_tyme = parent_tyme(s) + MIN_BRANCH_LENGTH;
/* Tyme cannot be greater than any children */
max_tyme = min_child_tyme(s) - MIN_BRANCH_LENGTH;
/*
* EXPERIMENTAL:
* Allow nodes to move pretty much anywhere by pushing others outta the way.
*/
/* First, find the absolute maximum and minimum tymes. */
/* Minimum tyme is somewhere past the root */
min_tyme = curtree->root->tyme + MIN_ROOT_TYME;
/* Max tyme is the minimum branch length times the maximal number of branches
* to any tip node. */
max_tyme = node_max_tyme(curtree, s);
/* Nothing to do if we can't move */
if ( max_tyme < min_tyme + 2.0 * MIN_BRANCH_LENGTH ) {
return false;
}
/* Fix a failure to enforce minimum branch lengths which occurs somewhere in
* dnamlk_add() */
if (s->tyme > max_tyme)
set_tyme(curtree, s, max_tyme);
current_node = s;
new_tyme = maximize(min_tyme, s->tyme, max_tyme, &cur_node_eval, epsilon, &success);
set_tyme(curtree, s, new_tyme);
return success;
} /* makenewv */
PHYLIPNEW-3.69.650/src/freqboot.c 0000664 0001750 0001750 00000064370 11616234204 013053 0000000 0000000 #include "phylip.h"
#include "seq.h"
/* version 3.6. (c) Copyright 1993-2004 by the University of Washington.
Written by Joseph Felsenstein, Akiko Fuseki, Sean Lamont, Andrew Keeffe,
and Doug Buxton.
Permission is granted to copy and use this program provided no fee is
charged for it and provided that this copyright notice is not removed. */
typedef enum {
seqs, morphology, restsites, genefreqs
} datatype;
typedef enum {
dna, rna, protein
} seqtype;
AjPPhyloFreq phylofreqs = NULL;
AjPPhyloProp phyloweights = NULL;
#ifndef OLDC
/* function prototypes */
//void getoptions(void);
void emboss_getoptions(char *pgm, int argc, char *argv[]);
void seqboot_inputnumbersfreq(AjPPhyloFreq);
void inputoptions(void);
void seqboot_inputdatafreq(AjPPhyloFreq);
void allocrest(void);
void allocnew(void);
void doinput(int argc, Char *argv[]);
void bootweights(void);
void sppermute(long);
void charpermute(long, long);
void writedata(void);
void writeweights(void);
void writecategories(void);
void writeauxdata(steptr, FILE*);
void writefactors(void);
void bootwrite(void);
void seqboot_inputaux(steptr, FILE*);
/* function prototypes */
#endif
FILE *outcatfile, *outweightfile, *outmixfile, *outancfile, *outfactfile;
Char infilename[FNMLNGTH], catfilename[FNMLNGTH], weightfilename[FNMLNGTH], mixfilename[FNMLNGTH], ancfilename[FNMLNGTH], factfilename[FNMLNGTH];
const char* outfilename;
AjPFile embossoutfile;
const char* outweightfilename;
AjPFile embossoutweightfile;
const char* outmixfilename;
AjPFile embossoutmixfile;
const char* outancfilename;
AjPFile embossoutancfile;
const char* outcatfilename;
AjPFile embossoutcatfile;
const char* outfactfilename;
AjPFile embossoutfactfile;
long sites, loci, maxalleles, groups, newsites, newersites,
newgroups, newergroups, nenzymes, reps, ws, blocksize, categs, maxnewsites;
boolean bootstrap, permute, ild, lockhart, jackknife, regular, xml, nexus,
weights, categories, factors, enzymes, all, justwts, progress, mixture,
firstrep, ancvar;
double fracsample;
datatype data;
seqtype seq;
steptr oldweight, where, how_many, newwhere, newhowmany,
newerwhere, newerhowmany, factorr, newerfactor, mixdata, ancdata;
steptr *charorder;
Char *factor;
long *alleles;
Char **nodep;
double **nodef;
long **sppord;
longer seed;
void emboss_getoptions(char *pgm, int argc, char *argv[])
{
AjPStr test = NULL;
AjPStr outputformat = NULL;
AjPStr typeofseq = NULL;
AjPStr justweights = NULL;
AjBool rewrite = false;
long inseed, inseed0;
data = genefreqs;
seq = dna;
bootstrap = false;
jackknife = false;
permute = false;
ild = false;
lockhart = false;
blocksize = 1;
regular = true;
fracsample = 1.0;
all = true;
reps = 100;
weights = false;
mixture = false;
ancvar = false;
categories = false;
justwts = false;
printdata = false;
dotdiff = true;
progress = true;
interleaved = true;
xml = false;
nexus = false;
factors = false;
enzymes = false;
embInitPV(pgm, argc, argv, "PHYLIPNEW",VERSION);
phylofreqs = ajAcdGetFrequencies("infile");
test = ajAcdGetListSingle("test");
if(ajStrMatchC(test, "b")) {
bootstrap = true;
regular = ajAcdGetToggle("regular");
if(regular) fracsample = 1.0;
else {
fracsample = ajAcdGetFloat("fracsample");
fracsample = fracsample/100.0;
}
blocksize = ajAcdGetInt("blocksize");
}
else if(ajStrMatchC(test, "j")) {
jackknife = true;
regular = ajAcdGetToggle("regular");
if(regular) fracsample = 0.5;
else {
fracsample = ajAcdGetFloat("fracsample");
fracsample = fracsample/100.0;
}
}
else if(ajStrMatchC(test, "c")) permute = true;
else if(ajStrMatchC(test, "o")) ild = true;
else if(ajStrMatchC(test, "s")) lockhart = true;
else if(ajStrMatchC(test, "r")) rewrite = true;
if(rewrite) {
if (data == seqs) {
outputformat = ajAcdGetListSingle("rewriteformat");
if(ajStrMatchC(outputformat, "n")) nexus = true;
else if(ajStrMatchC(outputformat, "x")) xml = true;
if( (nexus) || (xml) ) {
typeofseq = ajAcdGetListSingle("seqtype");
if(ajStrMatchC(typeofseq, "d")) seq = dna;
else if(ajStrMatchC(typeofseq, "r")) seq = rna;
else if(ajStrMatchC(typeofseq, "p")) seq = protein;
}
}
}
else{
reps = ajAcdGetInt("reps");
inseed = ajAcdGetInt("seed");
emboss_initseed(inseed, &inseed0, seed);
if(jackknife || bootstrap || permute) {
phyloweights = ajAcdGetProperties("weights");
if(phyloweights) weights = true;
}
if(!permute) {
justweights = ajAcdGetListSingle("justweights");
if(ajStrMatchC(justweights, "j")) justwts = true;
}
}
printdata = ajAcdGetBoolean("printdata");
if(printdata) dotdiff = ajAcdGetBoolean("dotdiff");
progress = ajAcdGetBoolean("progress");
embossoutfile = ajAcdGetOutfile("outfile");
emboss_openfile(embossoutfile, &outfile, &outfilename);
} /* emboss_getoptions */
void seqboot_inputnumbersfreq(AjPPhyloFreq freq)
{
/* read numbers of species and of sites */
long i;
spp = freq->Size;
sites = freq->Loci;
loci = sites;
maxalleles = 1;
if (!freq->ContChar) {
alleles = (long *)Malloc(sites*sizeof(long));
sites = 0;
for (i = 0; i < (loci); i++) {
alleles[i] = freq->Allele[i];
if (alleles[i] > maxalleles)
maxalleles = alleles[i];
sites += alleles[i];
}
}
} /* seqboot_inputnumbersfreq */
void inputoptions()
{
/* input the information on the options */
long weightsum, maxfactsize, i, j, k, l, m;
if (data == genefreqs) {
k = 0;
l = 0;
for (i = 0; i < (loci); i++) {
m = alleles[i];
k++;
for (j = 1; j <= m; j++) {
l++;
factorr[l - 1] = k;
}
}
} else {
for (i = 1; i <= (sites); i++)
factorr[i - 1] = i;
}
for (i = 0; i < (sites); i++)
oldweight[i] = 1;
if (weights)
inputweightsstr2(phyloweights->Str[0],0, sites, &weightsum, oldweight, &weights, "seqboot");
if (factors && printdata) {
for(i = 0; i < sites; i++)
factor[i] = (char)('0' + (factorr[i]%10));
printfactors(outfile, sites, factor, " (least significant digit)");
}
if (weights && printdata)
printweights(outfile, 0, sites, oldweight, "Sites");
for (i = 0; i < (loci); i++)
how_many[i] = 0;
for (i = 0; i < (loci); i++)
where[i] = 0;
for (i = 1; i <= (sites); i++) {
how_many[factorr[i - 1] - 1]++;
if (where[factorr[i - 1] - 1] == 0)
where[factorr[i - 1] - 1] = i;
}
groups = factorr[sites - 1];
newgroups = 0;
newsites = 0;
maxfactsize = 0;
for(i = 0 ; i < loci ; i++){
if(how_many[i] > maxfactsize){
maxfactsize = how_many[i];
}
}
maxnewsites = groups * maxfactsize;
allocnew();
for (i = 0; i < (groups); i++) {
if (oldweight[where[i] - 1] > 0) {
newgroups++;
newsites += how_many[i];
newwhere[newgroups - 1] = where[i];
newhowmany[newgroups - 1] = how_many[i];
}
}
} /* inputoptions */
void seqboot_inputdatafreq(AjPPhyloFreq freq)
{
/* input the names and sequences for each species */
long i, j, k, l, m, n;
double x;
ajint ipos=0;
nodef = (double **)Malloc(spp*sizeof(double *));
for (i = 0; i < (spp); i++)
nodef[i] = (double *)Malloc(sites*sizeof(double));
j = nmlngth + (sites + (sites - 1) / 10) / 2 - 5;
if (j < nmlngth - 1)
j = nmlngth - 1;
if (j > 37)
j = 37;
if (printdata) {
fprintf(outfile, "\nBootstrapping algorithm, version %s\n\n\n",VERSION);
if (bootstrap) {
if (blocksize > 1) {
if (regular)
fprintf(outfile, "Block-bootstrap with block size %ld\n\n", blocksize);
else
fprintf(outfile, "Partial (%2.0f%%) block-bootstrap with block size %ld\n\n",
100*fracsample, blocksize);
} else {
if (regular)
fprintf(outfile, "Bootstrap\n\n");
else
fprintf(outfile, "Partial (%2.0f%%) bootstrap\n\n", 100*fracsample);
}
} else {
if (jackknife) {
if (regular)
fprintf(outfile, "Delete-half Jackknife\n\n");
else
fprintf(outfile, "Delete-%2.0f%% Jackknife\n\n", 100*(1.0-fracsample));
} else {
if (permute) {
fprintf(outfile, "Species order permuted separately for each");
fprintf(outfile, " locus\n\n");
}
else {
if (ild) {
fprintf(outfile, "Locus");
fprintf(outfile, " order permuted\n\n");
} else {
if (lockhart)
fprintf(outfile, "Locus");
fprintf(outfile, " order permuted separately for each species\n\n");
}
}
}
}
fprintf(outfile, "%3ld species, %3ld loci\n\n", spp, loci);
fprintf(outfile, "Name");
for (i = 1; i <= j; i++)
putc(' ', outfile);
fprintf(outfile, "Data\n");
fprintf(outfile, "----");
for (i = 1; i <= j; i++)
putc(' ', outfile);
fprintf(outfile, "----\n\n");
}
for (i = 1; i <= (spp); i++) {
initnamefreq(freq,i - 1);
j = 1;
while (j <= sites) {
x = freq->Data[ipos++];
if ((unsigned)x > 1.0) {
printf("GENE FREQ OUTSIDE [0,1] in species %ld\n", i);
embExitBad();
} else {
nodef[i - 1][j - 1] = x;
j++;
}
}
}
if (!printdata)
return;
m = (sites - 1) / 8 + 1;
for (i = 1; i <= m; i++) {
for (j = 0; j < spp; j++) {
for (k = 0; k < nmlngth; k++)
putc(nayme[j][k], outfile);
fprintf(outfile, " ");
l = i * 8;
if (l > sites)
l = sites;
n = (i - 1) * 8;
for (k = n; k < l; k++) {
fprintf(outfile, "%8.5f", nodef[j][k]);
}
putc('\n', outfile);
}
putc('\n', outfile);
}
putc('\n', outfile);
} /* seqboot_inputdatafreq */
void allocrest()
{ /* allocate memory for bookkeeping arrays */
oldweight = (steptr)Malloc(sites*sizeof(long));
weight = (steptr)Malloc(sites*sizeof(long));
if (categories)
category = (steptr)Malloc(sites*sizeof(long));
if (mixture)
mixdata = (steptr)Malloc(sites*sizeof(long));
if (ancvar)
ancdata = (steptr)Malloc(sites*sizeof(long));
where = (steptr)Malloc(loci*sizeof(long));
how_many = (steptr)Malloc(loci*sizeof(long));
factor = (Char *)Malloc(sites*sizeof(Char));
factorr = (steptr)Malloc(sites*sizeof(long));
nayme = (naym *)Malloc(spp*sizeof(naym));
} /* allocrest */
void allocnew(void)
{ /* allocate memory for arrays that depend on the lenght of the
output sequence*/
long i;
newwhere = (steptr)Malloc(loci*sizeof(long));
newhowmany = (steptr)Malloc(loci*sizeof(long));
newerwhere = (steptr)Malloc(loci*sizeof(long));
newerhowmany = (steptr)Malloc(loci*sizeof(long));
newerfactor = (steptr)Malloc(maxnewsites*maxalleles*sizeof(long));
charorder = (steptr *)Malloc(spp*sizeof(steptr));
for (i = 0; i < spp; i++)
charorder[i] = (steptr)Malloc(maxnewsites*sizeof(long));
}
void doinput(int argc, Char *argv[])
{ /* reads the input data */
seqboot_inputnumbersfreq(phylofreqs);
allocrest();
inputoptions();
seqboot_inputdatafreq(phylofreqs);
} /* doinput */
void bootweights()
{ /* sets up weights by resampling data */
long i, j, k, blocks;
double p, q, r;
ws = newgroups;
for (i = 0; i < (ws); i++)
weight[i] = 0;
if (jackknife) {
if (fabs(newgroups*fracsample - (long)(newgroups*fracsample+0.5))
> 0.00001) {
if (randum(seed)
< (newgroups*fracsample - (long)(newgroups*fracsample))
/((long)(newgroups*fracsample+1.0)-(long)(newgroups*fracsample)))
q = (long)(newgroups*fracsample)+1;
else
q = (long)(newgroups*fracsample);
} else
q = (long)(newgroups*fracsample+0.5);
r = newgroups;
p = q / r;
ws = 0;
for (i = 0; i < (newgroups); i++) {
if (randum(seed) < p) {
weight[i]++;
ws++;
q--;
}
r--;
if (i + 1 < newgroups)
p = q / r;
}
} else if (permute) {
for (i = 0; i < (newgroups); i++)
weight[i] = 1;
} else if (bootstrap) {
blocks = fracsample * newgroups / blocksize;
for (i = 1; i <= (blocks); i++) {
j = (long)(newgroups * randum(seed)) + 1;
for (k = 0; k < blocksize; k++) {
weight[j - 1]++;
j++;
if (j > newgroups)
j = 1;
}
}
} else /* case of rewriting data */
for (i = 0; i < (newgroups); i++)
weight[i] = 1;
for (i = 0; i < (newgroups); i++)
newerwhere[i] = 0;
for (i = 0; i < (newgroups); i++)
newerhowmany[i] = 0;
newergroups = 0;
newersites = 0;
for (i = 0; i < (newgroups); i++) {
for (j = 1; j <= (weight[i]); j++) {
newergroups++;
for (k = 1; k <= (newhowmany[i]); k++) {
newersites++;
newerfactor[newersites - 1] = newergroups;
}
newerwhere[newergroups - 1] = newwhere[i];
newerhowmany[newergroups - 1] = newhowmany[i];
}
}
} /* bootweights */
void sppermute(long n)
{ /* permute the species order as given in array sppord */
long i, j, k;
for (i = 1; i <= (spp - 1); i++) {
k = (long)((i+1) * randum(seed));
j = sppord[n - 1][i];
sppord[n - 1][i] = sppord[n - 1][k];
sppord[n - 1][k] = j;
}
} /* sppermute */
void charpermute(long m, long n)
{ /* permute the n+1 characters of species m+1 */
long i, j, k;
for (i = 1; i <= (n - 1); i++) {
k = (long)((i+1) * randum(seed));
j = charorder[m][i];
charorder[m][i] = charorder[m][k];
charorder[m][k] = j;
}
} /* charpermute */
void writedata()
{
/* write out one set of bootstrapped sequences */
long i, j, k, l, m, n, n2=0;
double x;
Char charstate;
sppord = (long **)Malloc(newergroups*sizeof(long *));
for (i = 0; i < (newergroups); i++)
sppord[i] = (long *)Malloc(spp*sizeof(long));
for (j = 1; j <= spp; j++)
sppord[0][j - 1] = j;
for (i = 1; i < newergroups; i++) {
for (j = 1; j <= (spp); j++)
sppord[i][j - 1] = sppord[i - 1][j - 1];
}
if (!justwts || permute) {
if (data == restsites && enzymes)
fprintf(outfile, "%5ld %5ld% 4ld\n", spp, newergroups, nenzymes);
else if (data == genefreqs)
fprintf(outfile, "%5ld %5ld\n", spp, newergroups);
else {
if ((data == seqs)
&& !(bootstrap || jackknife || permute || ild || lockhart) && xml)
fprintf(outfile, "\n");
else
if (!(bootstrap || jackknife || permute || ild || lockhart) && nexus) {
fprintf(outfile, "#NEXUS\n");
fprintf(outfile, "BEGIN DATA\n");
fprintf(outfile, " DIMENSIONS NTAX=%ld NCHAR=%ld;\n",
spp, newersites);
fprintf(outfile, " FORMAT");
fprintf(outfile, " interleave");
fprintf(outfile, " DATATYPE=");
if (data == seqs) {
switch (seq) {
case (dna): fprintf(outfile, "DNA missing=N gap=-"); break;
case (rna): fprintf(outfile, "RNA missing=N gap=-"); break;
case (protein):
fprintf(outfile, "protein missing=? gap=-");
break;
}
}
if (data == morphology)
fprintf(outfile, "STANDARD");
fprintf(outfile, ";\n MATRIX\n");
}
else fprintf(outfile, "%5ld %5ld\n", spp, newersites);
}
if (data == genefreqs) {
for (i = 0; i < (newergroups); i++)
fprintf(outfile, " %3ld", alleles[factorr[newerwhere[i] - 1] - 1]);
putc('\n', outfile);
}
}
l = 1;
if ((!(bootstrap || jackknife || permute || ild || lockhart | nexus))
&& ((data == seqs) || (data == restsites))) {
interleaved = !interleaved;
if (!(bootstrap || jackknife || permute || ild || lockhart) && xml)
interleaved = false;
}
if (interleaved)
m = 60;
else
m = newergroups;
do {
if (m > newergroups)
m = newergroups;
for (j = 0; j < spp; j++) {
n = 0;
if ((l == 1) || (interleaved && nexus)) {
if (!(bootstrap || jackknife || permute || ild || lockhart) && xml) {
fprintf(outfile, " \n");
fprintf(outfile, " ");
}
n2 = nmlngth-1;
if (!(bootstrap || jackknife || permute || ild || lockhart)
&& (xml || nexus)) {
while (nayme[j][n2] == ' ')
n2--;
}
if (nexus)
fprintf(outfile, " ");
for (k = 0; k <= n2; k++)
if (nexus && (nayme[j][k] == ' ') && (k < n2))
putc('_', outfile);
else
putc(nayme[j][k], outfile);
if (!(bootstrap || jackknife || permute || ild || lockhart) && xml)
fprintf(outfile, "\n ");
} else {
if (!(bootstrap || jackknife || permute || ild || lockhart) && xml) {
fprintf(outfile, " ");
}
else {
for (k = 1; k <= nmlngth; k++)
putc(' ', outfile);
}
}
if (nexus)
for (k = 0; k < nmlngth+1-n2; k++)
fprintf(outfile, " ");
for (k = l - 1; k < m; k++) {
if (permute && j + 1 == 1)
sppermute(newerfactor[n]); /* we can assume chars not permuted */
for (n2 = -1; n2 <= (newerhowmany[k] - 2); n2++) {
n++;
if (data == genefreqs) {
if (n > 1 && (n & 7) == 1)
fprintf(outfile, "\n ");
x = nodef[sppord[newerfactor[charorder[j][n - 1]] - 1][j] - 1]
[newerwhere[charorder[j][k]] + n2];
fprintf(outfile, "%8.5f", x);
} else {
if (!(bootstrap || jackknife || permute || ild || lockhart) && xml
&& (n > 1) && (n % 60 == 1))
fprintf(outfile, "\n ");
else if (!nexus && !interleaved && (n > 1) && (n % 60 == 1))
fprintf(outfile, "\n ");
charstate = nodep[sppord[newerfactor[charorder[j][n - 1]] - 1]
[j] - 1][newerwhere[charorder[j][k]] + n2];
putc(charstate, outfile);
if (n % 10 == 0 && n % 60 != 0)
putc(' ', outfile);
}
}
}
if (!(bootstrap || jackknife || permute || ild || lockhart ) && xml) {
fprintf(outfile, "\n \n");
}
putc('\n', outfile);
}
if (interleaved) {
if ((m <= newersites) && (newersites > 60))
putc('\n', outfile);
l += 60;
m += 60;
}
} while (interleaved && l <= newersites);
if ((data == seqs) &&
(!(bootstrap || jackknife || permute || ild || lockhart) && xml))
fprintf(outfile, "\n");
if (!(bootstrap || jackknife || permute || ild || lockhart) && nexus)
fprintf(outfile, " ;\nEND;\n");
for (i = 0; i < (newergroups); i++)
free(sppord[i]);
free(sppord);
} /* writedata */
void writeweights()
{ /* write out one set of post-bootstrapping weights */
long j, k, l, m, n, o;
j = 0;
l = 1;
if (interleaved)
m = 60;
else
m = sites;
do {
if(m > sites)
m = sites;
n = 0;
for (k = l - 1; k < m; k++) {
for(o = 0 ; o < how_many[k] ; o++){
if(oldweight[k]==0){
fprintf(outweightfile, "0");
j++;
}
else{
if (weight[k-j] < 10)
fprintf(outweightfile, "%c", (char)('0'+weight[k-j]));
else
fprintf(outweightfile, "%c", (char)('A'+weight[k-j]-10));
n++;
if (!interleaved && n > 1 && n % 60 == 1) {
fprintf(outweightfile, "\n");
if (n % 10 == 0 && n % 60 != 0)
putc(' ', outweightfile);
}
}
}
}
putc('\n', outweightfile);
if (interleaved) {
l += 60;
m += 60;
}
} while (interleaved && l <= sites);
} /* writeweights */
void writecategories()
{
/* write out categories for the bootstrapped sequences */
long k, l, m, n, n2;
Char charstate;
if(justwts){
if (interleaved)
m = 60;
else
m = sites;
l=1;
do {
if(m > sites)
m = sites;
n=0;
for(k=l-1 ; k < m ; k++){
n++;
if (!interleaved && n > 1 && n % 60 == 1)
fprintf(outcatfile, "\n ");
charstate = '0' + category[k];
putc(charstate, outcatfile);
}
if (interleaved) {
l += 60;
m += 60;
}
}while(interleaved && l <= sites);
fprintf(outcatfile, "\n");
return;
}
l = 1;
if (interleaved)
m = 60;
else
m = newergroups;
do {
if (m > newergroups)
m = newergroups;
n = 0;
for (k = l - 1; k < m; k++) {
for (n2 = -1; n2 <= (newerhowmany[k] - 2); n2++) {
n++;
if (!interleaved && n > 1 && n % 60 == 1)
fprintf(outcatfile, "\n ");
charstate = '0' + category[newerwhere[k] + n2];
putc(charstate, outcatfile);
if (n % 10 == 0 && n % 60 != 0)
putc(' ', outcatfile);
}
}
if (interleaved) {
l += 60;
m += 60;
}
} while (interleaved && l <= newersites);
fprintf(outcatfile, "\n");
} /* writecategories */
void writeauxdata(steptr auxdata, FILE *outauxfile)
{
/* write out auxiliary option data (mixtures, ancestors, ect) to
appropriate file. Samples parralel to data, or just gives one
output entry if justwts is true */
long k, l, m, n, n2;
Char charstate;
/* if we just output weights (justwts), and this is first set
just output the data unsampled */
if(justwts){
if(firstrep){
if (interleaved)
m = 60;
else
m = sites;
l=1;
do {
if(m > sites)
m = sites;
n = 0;
for(k=l-1 ; k < m ; k++){
n++;
if (!interleaved && n > 1 && n % 60 == 1)
fprintf(outauxfile, "\n ");
charstate = auxdata[k];
putc(charstate, outauxfile);
}
if (interleaved) {
l += 60;
m += 60;
}
}while(interleaved && l <= sites);
fprintf(outauxfile, "\n");
}
return;
}
l = 1;
if (interleaved)
m = 60;
else
m = newergroups;
do {
if (m > newergroups)
m = newergroups;
n = 0;
for (k = l - 1; k < m; k++) {
for (n2 = -1; n2 <= (newerhowmany[k] - 2); n2++) {
n++;
if (!interleaved && n > 1 && n % 60 == 1)
fprintf(outauxfile, "\n ");
charstate = auxdata[newerwhere[k] + n2];
putc(charstate, outauxfile);
if (n % 10 == 0 && n % 60 != 0)
putc(' ', outauxfile);
}
}
if (interleaved) {
l += 60;
m += 60;
}
} while (interleaved && l <= newersites);
fprintf(outauxfile, "\n");
} /* writeauxdata */
void writefactors(void)
{
long k, l, m, n, prevfact, writesites;
char symbol;
steptr wfactor;
if(!justwts || firstrep){
if(justwts){
writesites = sites;
wfactor = factorr;
} else {
writesites = newersites;
wfactor = newerfactor;
}
prevfact = wfactor[0];
symbol = '+';
if (interleaved)
m = 60;
else
m = writesites;
l=1;
do {
if(m > writesites)
m = writesites;
n = 0;
for(k=l-1 ; k < m ; k++){
n++;
if (!interleaved && n > 1 && n % 60 == 1)
fprintf(outfactfile, "\n ");
if(prevfact != wfactor[k]){
symbol = (symbol == '+') ? '-' : '+';
prevfact = wfactor[k];
}
putc(symbol, outfactfile);
if (n % 10 == 0 && n % 60 != 0)
putc(' ', outfactfile);
}
if (interleaved) {
l += 60;
m += 60;
}
}while(interleaved && l <= writesites);
fprintf(outfactfile, "\n");
}
} /* writefactors */
void bootwrite()
{ /* does bootstrapping and writes out data sets */
long i, j, rr, repdiv10;
if (!(bootstrap || jackknife || permute || ild || lockhart))
reps = 1;
repdiv10 = reps / 10;
if (repdiv10 < 1)
repdiv10 = 1;
if (progress)
putchar('\n');
for (rr = 1; rr <= (reps); rr++) {
for (i = 0; i < spp; i++)
for (j = 0; j < maxnewsites; j++)
charorder[i][j] = j;
if(rr==1)
firstrep = true;
else
firstrep = false;
if (ild) {
charpermute(0, maxnewsites);
for (i = 1; i < spp; i++)
for (j = 0; j < maxnewsites; j++)
charorder[i][j] = charorder[0][j];
}
if (lockhart)
for (i = 0; i < spp; i++)
charpermute(i, maxnewsites);
bootweights();
if (!justwts || permute || ild || lockhart)
writedata();
if (justwts && !(permute || ild || lockhart))
writeweights();
if (categories)
writecategories();
if (factors)
writefactors();
if (mixture)
writeauxdata(mixdata, outmixfile);
if (ancvar)
writeauxdata(ancdata, outancfile);
if (progress && (bootstrap || jackknife || permute || ild || lockhart)
&& ((reps < 10) || rr % repdiv10 == 0)) {
printf("completed replicate number %4ld\n", rr);
#ifdef WIN32
phyFillScreenColor();
#endif
}
}
if (progress) {
if (justwts)
printf("\nOutput weights written to file \"%s\"\n\n", outweightfilename);
else
printf("\nOutput written to file \"%s\"\n\n", outfilename);
}
} /* bootwrite */
int main(int argc, Char *argv[])
{ /* Read in sequences or frequencies and bootstrap or jackknife them */
#ifdef MAC
argc = 1; /* macsetup("SeqBoot",""); */
argv[0] = "SeqBoot";
#endif
init(argc,argv);
emboss_getoptions("ffreqboot", argc, argv);
ibmpc = IBMCRT;
ansi = ANSICRT;
doinput(argc, argv);
bootwrite();
FClose(infile);
if (weights)
FClose(weightfile);
if (categories) {
FClose(catfile);
FClose(outcatfile);
}
if(mixture)
FClose(outmixfile);
if(ancvar)
FClose(outancfile);
if (justwts && !permute) {
FClose(outweightfile);
}
else
FClose(outfile);
#ifdef MAC
fixmacfile(outfilename);
if (justwts && !permute)
fixmacfile(outweightfilename);
if (categories)
fixmacfile(outcatfilename);
if (mixture)
fixmacfile(outmixfilename);
#endif
if(progress)
printf("Done.\n\n");
#ifdef WIN32
phyRestoreConsoleAttributes();
#endif
embExit();
return 0;
}
PHYLIPNEW-3.69.650/src/dolpenny.c 0000664 0001750 0001750 00000041015 11616234204 013051 0000000 0000000 #include "phylip.h"
#include "disc.h"
#include "dollo.h"
/* version 3.6. (c) Copyright 1993-2004 by the University of Washington.
Written by Joseph Felsenstein, Akiko Fuseki, Sean Lamont, and Andrew Keeffe.
Permission is granted to copy and use this program provided no fee is
charged for it and provided that this copyright notice is not removed. */
#define maxtrees 1000 /* maximum number of trees to be printed out */
#define often 100 /* how often to notify how many trees examined */
#define many 1000 /* how many multiples of howoften before stop */
typedef long *treenumbers;
typedef double *valptr;
typedef long *placeptr;
AjPPhyloState* phylostates = NULL;
AjPPhyloProp phyloanc = NULL;
AjPPhyloProp phyloweights = NULL;
#ifndef OLDC
/* function prototypes */
//void getoptions(void);
void emboss_getoptions(char *pgm, int argc, char *argv[]);
void allocrest(void);
void doinit(void);
void inputoptions(void);
void doinput(void);
void preorder(node *);
void evaluate(node *);
void addtraverse(node *, node *, node *, placeptr, valptr, long *);
void addit(long);
void describe(void);
void maketree(void);
/* function prototypes */
#endif
Char infilename[FNMLNGTH], weightfilename[FNMLNGTH], ancfilename[FNMLNGTH];
const char* outfilename;
const char* outtreename;
AjPFile embossoutfile;
AjPFile embossouttree;
node *root;
long howmany, howoften, col, msets, ith;
boolean weights, thresh, ancvar, questions, dollo, simple, trout,
progress, treeprint, stepbox, ancseq,
mulsets, firstset, justwts;
boolean *ancone, *anczero, *ancone0, *anczero0;
pointptr treenode; /* pointers to all nodes in tree */
double fracdone, fracinc;
double threshold;
double *threshwt;
boolean *added;
Char *guess;
steptr numsteps, numsone, numszero;
gbit *garbage;
long **bestorders, **bestrees;
/* Local variables for maketree, propagated globally for C version: */
long examined, mults;
boolean firsttime, done;
double like, bestyet;
treenumbers current, order;
long fullset;
bitptr zeroanc, oneanc;
bitptr stps;
void emboss_getoptions(char *pgm, int argc, char *argv[])
{
ajint numseqs=0;
ajint numwts=0;
AjPStr method = NULL;
howoften = often;
howmany = many;
simple = true;
thresh = false;
threshold = spp;
trout = true;
weights = false;
justwts = false;
ancvar = false;
dollo = true;
printdata = false;
progress = true;
treeprint = true;
stepbox = false;
ancseq = false;
mulsets = false;
msets = 1;
embInitPV(pgm, argc, argv, "PHYLIPNEW",VERSION);
phylostates = ajAcdGetDiscretestates("infile");
while (phylostates[numseqs])
numseqs++;
phyloweights = ajAcdGetProperties("weights");
if (phyloweights)
{
weights = true;
numwts = ajPhyloPropGetSize(phyloweights);
}
if (numseqs > 1) {
mulsets = true;
msets = numseqs;
}
else if (numwts > 1) {
mulsets = true;
msets = numwts;
justwts = true;
}
method = ajAcdGetListSingle("method");
if(ajStrMatchC(method, "d")) dollo = true;
else dollo = false;
phyloanc = ajAcdGetProperties("ancfile");
if(phyloanc) ancvar = true;
howmany = ajAcdGetInt("howmany");
howoften = ajAcdGetInt("howoften");
simple = ajAcdGetBoolean("simple");
thresh = ajAcdGetToggle("dothreshold");
if(thresh) ajAcdGetFloat("threshold");
printdata = ajAcdGetBoolean("printdata");
progress = ajAcdGetBoolean("progress");
treeprint = ajAcdGetBoolean("treeprint");
trout = ajAcdGetToggle("trout");
stepbox = ajAcdGetBoolean("stepbox");
ancseq = ajAcdGetBoolean("ancseq");
embossoutfile = ajAcdGetOutfile("outfile");
emboss_openfile(embossoutfile, &outfile, &outfilename);
if(trout) {
embossouttree = ajAcdGetOutfile("outtreefile");
emboss_openfile(embossouttree, &outtree, &outtreename);
}
fprintf(outfile, "\nPenny algorithm for Dollo or polymorphism parsimony, version %s\n",VERSION);
fprintf(outfile, " branch-and-bound to find all most parsimonious trees\n\n");
} /* emboss_getoptions */
void allocrest()
{
long i;
extras = (long *)Malloc(chars*sizeof(long));
weight = (long *)Malloc(chars*sizeof(long));
threshwt = (double *)Malloc(chars*sizeof(double));
guess = (Char *)Malloc(chars*sizeof(Char));
numsteps = (long *)Malloc(chars*sizeof(long));
numszero = (long *)Malloc(chars*sizeof(long));
numsone = (long *)Malloc(chars*sizeof(long));
bestorders = (long **)Malloc(maxtrees*sizeof(long *));
bestrees = (long **)Malloc(maxtrees*sizeof(long *));
for (i = 1; i <= maxtrees; i++) {
bestorders[i - 1] = (long *)Malloc(spp*sizeof(long));
bestrees[i - 1] = (long *)Malloc(spp*sizeof(long));
}
current = (treenumbers)Malloc(spp*sizeof(long));
order = (treenumbers)Malloc(spp*sizeof(long));
nayme = (naym *)Malloc(spp*sizeof(naym));
added = (boolean *)Malloc(nonodes*sizeof(boolean));
ancone = (boolean *)Malloc(chars*sizeof(boolean));
anczero = (boolean *)Malloc(chars*sizeof(boolean));
ancone0 = (boolean *)Malloc(chars*sizeof(boolean));
anczero0 = (boolean *)Malloc(chars*sizeof(boolean));
zeroanc = (bitptr)Malloc(words*sizeof(long));
oneanc = (bitptr)Malloc(words*sizeof(long));
} /* allocrest */
void doinit()
{
/* initializes variables */
inputnumbersstate(phylostates[0], &spp, &chars, &nonodes, 1);
words = chars / bits + 1;
if (printdata)
fprintf(outfile, "%2ld species, %3ld characters\n", spp, chars);
alloctree(&treenode);
setuptree(treenode);
allocrest();
} /* doinit */
void inputoptions()
{
/* input the information on the options */
long i;
if(justwts){
if(firstset){
if (ancvar) {
inputancestorsstr(phyloanc->Str[0], anczero0, ancone0);
}
}
for (i = 0; i < (chars); i++)
weight[i] = 1;
inputweightsstr(phyloweights->Str[0], chars, weight, &weights);
}
else {
if (!firstset)
samenumspstate(phylostates[ith-1], &chars, ith);
for (i = 0; i < (chars); i++)
weight[i] = 1;
if (ancvar)
inputancestorsstr(phyloanc->Str[0], anczero0, ancone0);
if (weights)
inputweightsstr(phyloweights->Str[ith-1], chars, weight, &weights);
}
for (i = 0; i < (chars); i++) {
if (!ancvar) {
anczero[i] = true;
ancone[i] = false;
} else {
anczero[i] = anczero0[i];
ancone[i] = ancone0[i];
}
}
questions = false;
if (!thresh)
threshold = spp;
for (i = 0; i < (chars); i++) {
questions = (questions || (ancone[i] && anczero[i]));
threshwt[i] = threshold * weight[i];
}
} /* inputoptions */
void doinput()
{
/* reads the input data */
inputoptions();
if(!justwts || firstset)
disc_inputdata(phylostates[ith-1], treenode, dollo, printdata, outfile);
} /* doinput */
void preorder(node *p)
{
/* go back up tree setting up and counting interior node
states */
long i;
if (!p->tip) {
correct(p, fullset, dollo, zeroanc, treenode);
preorder(p->next->back);
preorder(p->next->next->back);
}
if (p->back == NULL)
return;
if (dollo) {
for (i = 0; i < (words); i++)
stps[i] = (treenode[p->back->index - 1]->stateone[i] & p->statezero[i] &
zeroanc[i]) |
(treenode[p->back->index - 1]->statezero[i] & p->stateone[i] &
fullset & (~zeroanc[i]));
} else {
for (i = 0; i < (words); i++)
stps[i] = treenode[p->back->index - 1]->stateone[i] &
treenode[p->back->index - 1]->statezero[i] & p->stateone[i] &
p->statezero[i];
}
count(stps, zeroanc, numszero, numsone);
} /* preorder */
void evaluate(node *r)
{
/* Determines the number of losses or polymorphisms needed
for a tree. This is the minimum number needed to evolve
chars on this tree */
long i, stepnum, smaller;
double sum;
sum = 0.0;
for (i = 0; i < (chars); i++) {
numszero[i] = 0;
numsone[i] = 0;
}
for (i = 0; i < (words); i++)
zeroanc[i] = fullset;
postorder(r);
preorder(r);
for (i = 0; i < (words); i++)
zeroanc[i] = 0;
postorder(r);
preorder(r);
for (i = 0; i < (chars); i++) {
smaller = spp * weight[i];
numsteps[i] = smaller;
if (anczero[i]) {
numsteps[i] = numszero[i];
smaller = numszero[i];
}
if (ancone[i] && numsone[i] < smaller)
numsteps[i] = numsone[i];
stepnum = numsteps[i] + extras[i];
if (stepnum <= threshwt[i])
sum += stepnum;
else
sum += threshwt[i];
guess[i] = '?';
if (!ancone[i] || (anczero[i] && numszero[i] < numsone[i]))
guess[i] = '0';
else if (!anczero[i] || (ancone[i] && numsone[i] < numszero[i]))
guess[i] = '1';
}
if (examined == 0 && mults == 0)
bestyet = -1.0;
like = sum;
} /* evaluate */
void addtraverse(node *a, node *b, node *c, placeptr place,
valptr valyew, long *n)
{
/* traverse all places to add b */
if (done)
return;
add(a, b, c, &root, treenode);
(*n)++;
evaluate(root);
examined++;
if (examined == howoften) {
examined = 0;
mults++;
if (mults == howmany)
done = true;
if (progress) {
printf("%6ld",mults);
if (bestyet >= 0)
printf("%18.5f", bestyet);
else
printf(" - ");
printf("%17ld%20.2f\n", nextree - 1, fracdone * 100);
#ifdef WIN32
phyFillScreenColor();
#endif
}
}
valyew[*n - 1] = like;
place[*n - 1] = a->index;
re_move(&b, &c, &root, treenode);
if (!a->tip) {
addtraverse(a->next->back, b, c, place,valyew,n);
addtraverse(a->next->next->back, b, c, place,valyew,n);
}
} /* addtraverse */
void addit(long m)
{
/* adds the species one by one, recursively */
long n;
valptr valyew;
placeptr place;
long i, j, n1, besttoadd = 0;
valptr bestval;
placeptr bestplace;
double oldfrac, oldfdone, sum, bestsum;
valyew = (valptr)Malloc(nonodes*sizeof(double));
bestval = (valptr)Malloc(nonodes*sizeof(double));
place = (placeptr)Malloc(nonodes*sizeof(long));
bestplace = (placeptr)Malloc(nonodes*sizeof(long));
if (simple && !firsttime) {
n = 0;
added[order[m - 1] - 1] = true;
addtraverse(root, treenode[order[m - 1] - 1], treenode[spp + m - 2],
place, valyew, &n);
besttoadd = order[m - 1];
memcpy(bestplace, place, nonodes*sizeof(long));
memcpy(bestval, valyew, nonodes*sizeof(double));
} else {
bestsum = -1.0;
for (i = 1; i <= (spp); i++) {
if (!added[i - 1]) {
n = 0;
added[i - 1] = true;
addtraverse(root, treenode[i - 1], treenode[spp + m - 2],
place, valyew, &n);
added[i - 1] = false;
sum = 0.0;
for (j = 0; j < n; j++)
sum += valyew[j];
if (sum > bestsum) {
bestsum = sum;
besttoadd = i;
memcpy(bestplace, place, nonodes*sizeof(long));
memcpy(bestval, valyew, nonodes*sizeof(double));
}
}
}
}
order[m - 1] = besttoadd;
memcpy(place, bestplace, nonodes*sizeof(long));
memcpy(valyew, bestval, nonodes*sizeof(double));
shellsort(valyew, place, n);
oldfrac = fracinc;
oldfdone = fracdone;
n1 = 0;
for (i = 0; i < (n); i++) {
if (valyew[i] <= bestyet || bestyet < 0.0)
n1++;
}
if (n1 > 0)
fracinc /= n1;
for (i = 0; i < n; i++) {
if (valyew[i] <=bestyet ||bestyet < 0.0) {
current[m - 1] = place[i];
add(treenode[place[i] - 1], treenode[besttoadd - 1],
treenode[spp + m - 2], &root, treenode);
added[besttoadd - 1] = true;
if (m < spp)
addit(m + 1);
else {
if (valyew[i] < bestyet || bestyet < 0.0) {
nextree = 1;
bestyet = valyew[i];
}
if (nextree <= maxtrees) {
memcpy(bestorders[nextree - 1], order,
spp*sizeof(long));
memcpy(bestrees[nextree - 1], current,
spp*sizeof(long));
}
nextree++;
firsttime = false;
}
re_move(&treenode[besttoadd - 1], &treenode[spp + m - 2], &root, treenode);
added[besttoadd - 1] = false;
}
fracdone += fracinc;
}
fracinc = oldfrac;
fracdone = oldfdone;
free(valyew);
free(bestval);
free(place);
free(bestplace);
} /* addit */
void describe()
{
/* prints ancestors, steps and table of numbers of steps in
each character */
if (stepbox) {
putc('\n', outfile);
writesteps(weights, dollo, numsteps);
}
if (questions)
guesstates(guess);
if (ancseq) {
hypstates(fullset, dollo, guess, treenode, root, garbage, zeroanc, oneanc);
putc('\n', outfile);
}
putc('\n', outfile);
if (trout) {
col = 0;
treeout(root, nextree, &col, root);
}
} /* describe */
void maketree()
{
/* tree construction recursively by branch and bound */
long i, j, k;
node *dummy;
fullset = (1L << (bits + 1)) - (1L << 1);
if (progress) {
printf("\nHow many\n");
printf("trees looked Approximate\n");
printf("at so far Length of How many percentage\n");
printf("(multiples shortest tree trees this long searched\n");
printf("of %4ld): found so far found so far so far\n",
howoften);
printf("---------- ------------ ------------ ------------\n");
#ifdef WIN32
phyFillScreenColor();
#endif
}
done = false;
mults = 0;
examined = 0;
nextree = 1;
root = treenode[0];
firsttime = true;
for (i = 0; i < (spp); i++)
added[i] = false;
added[0] = true;
order[0] = 1;
k = 2;
fracdone = 0.0;
fracinc = 1.0;
bestyet = -1.0;
stps = (bitptr)Malloc(words*sizeof(long));
addit(k);
if (done) {
if (progress) {
printf("Search broken off! Not guaranteed to\n");
printf(" have found the most parsimonious trees.\n");
}
if (treeprint) {
fprintf(outfile, "Search broken off! Not guaranteed to\n");
fprintf(outfile, " have found the most parsimonious\n");
fprintf(outfile, " trees, but here is what we found:\n");
}
}
if (treeprint) {
fprintf(outfile, "\nrequires a total of %18.3f\n\n", bestyet);
if (nextree == 2)
fprintf(outfile, "One most parsimonious tree found:\n");
else
fprintf(outfile, "%5ld trees in all found\n", nextree - 1);
}
if (nextree > maxtrees + 1) {
if (treeprint)
fprintf(outfile, "here are the first%4ld of them\n", (long)maxtrees);
nextree = maxtrees + 1;
}
if (treeprint)
putc('\n', outfile);
for (i = 0; i < (spp); i++)
added[i] = true;
for (i = 0; i <= (nextree - 2); i++) {
for (j = k; j <= (spp); j++)
add(treenode[bestrees[i][j - 1] - 1],
treenode[bestorders[i][j - 1] - 1], treenode[spp + j - 2],
&root, treenode);
evaluate(root);
printree(1.0, treeprint, root);
describe();
for (j = k - 1; j < (spp); j++)
re_move(&treenode[bestorders[i][j] - 1], &dummy, &root, treenode);
}
if (progress) {
printf("\nOutput written to file \"%s\"\n\n", outfilename);
if (trout)
printf("Trees also written onto file \"%s\"\n\n", outtreename);
}
free(stps);
if (ancseq)
freegarbage(&garbage);
} /* maketree */
int main(int argc, Char *argv[])
{ /* branch-and-bound method for Dollo, polymorphism parsimony */
/* Reads in the number of species, number of characters,
options and data. Then finds all most parsimonious trees */
#ifdef MAC
argc = 1; /* macsetup("Dolpenny",""); */
argv[0] = "Dolpenny";
#endif
init(argc, argv);
emboss_getoptions("fdolpenny", argc, argv);
ibmpc = IBMCRT;
ansi = ANSICRT;
garbage = NULL;
firstset = true;
bits = 8*sizeof(long) - 1;
doinit();
if(ancvar)
fprintf(outfile,"%s parsimony method\n\n",dollo ? "Dollo" : "Polymorphism");
for (ith = 1; ith <= msets; ith++) {
doinput();
if (msets > 1 && !justwts) {
fprintf(outfile, "Data set # %ld:\n\n",ith);
if (progress)
printf("\nData set # %ld:\n",ith);
}
if (justwts){
fprintf(outfile, "Weights set # %ld:\n\n", ith);
if (progress)
printf("\nWeights set # %ld:\n\n", ith);
}
if (printdata){
if (weights || justwts)
printweights(outfile, 0, chars, weight, "Characters");
if (ancvar)
printancestors(outfile, anczero, ancone);
}
if (ith == 1)
firstset = false;
maketree();
}
FClose(infile);
FClose(outfile);
FClose(outtree);
#ifdef MAC
fixmacfile(outfilename);
fixmacfile(outtreename);
#endif
#ifdef WIN32
phyRestoreConsoleAttributes();
#endif
embExit();
return 0;
} /* branch-and-bound method for Dollo, polymorphism parsimony */
PHYLIPNEW-3.69.650/src/factor.c 0000664 0001750 0001750 00000036137 11305225544 012512 0000000 0000000
#include "phylip.h"
/* version 3.6. (c) Copyright 1988-2004 by the University of Washington.
A program to factor multistate character trees.
Originally version 29 May 1983 by C. A. Meacham, Botany Department,
University of Georgia
Additional code by Joe Felsenstein, 1988-1991
C version code by Akiko Fuseki, Sean Lamont, and Andrew Keeffe.
Permission is granted to copy and use this program provided no fee is
charged for it and provided that this copyright notice is not removed. */
#define maxstates 20 /* Maximum number of states in multi chars */
#define maxoutput 80 /* Maximum length of output line */
#define sizearray 5000 /* Size of symbarray; must be >= the sum of */
/* squares of the number of states in each multi*/
/* char to be factored */
#define factchar ':' /* character to indicate state connections */
#define unkchar '?' /* input character to indicate state unknown */
typedef struct statenode { /* Node of multifurcating tree */
struct statenode *ancstr, *sibling, *descendant;
Char state; /* Symbol of character state */
long edge; /* Number of subtending edge */
} statenode;
AjPStr rdline = NULL;
#ifndef OLDC
/* function prototypes */
//void getoptions(void);
void emboss_getoptions(char *pgm, int argc, char *argv[]);
void readtree(void);
void attachnodes(statenode *, Char *);
void maketree(statenode *, Char *);
void construct(void);
void numberedges(statenode *, long *);
void factortree(void);
void dotrees(void);
void writech(Char ch, long *, FILE *outauxfile);
void writefactors(long *);
void writeancestor(long *);
void doeu(long *, long);
void dodatamatrix(void);
/* function prototypes */
#endif
FILE *outfactfile, *outancfile;
Char infilename[FNMLNGTH];
const char* outfilename;
const char* outfactname;
const char* outancname;
AjPFile inputfile;
AjPFile embossoutfile;
AjPFile embossoutfact;
AjPFile embossoutanc;
long neus, nchars, charindex, lastindex;
Char ch;
boolean ancstrrequest, factorrequest, rooted, progress;
Char symbarray[sizearray];
/* Holds multi symbols and their factored equivs */
long *charnum; /* Multis */
long *chstart; /* Position of each */
long *numstates; /* Number of states */
Char *ancsymbol; /* Ancestral state */
/* local variables for dotrees, propagated to global level. */
long npairs, offset, charnumber, nstates;
statenode *root;
Char pair[maxstates][2];
statenode *nodes[maxstates];
void emboss_getoptions(char *pgm, int argc, char *argv[])
{
ibmpc = IBMCRT;
ansi = ANSICRT;
progress = true;
factorrequest = false;
ancstrrequest = false;
embInitPV(pgm, argc, argv, "PHYLIPNEW",VERSION);
inputfile = ajAcdGetInfile("infile");
factorrequest = ajAcdGetBoolean("factors");
ancstrrequest = ajAcdGetBoolean("anc");
progress = ajAcdGetBoolean("progress");
embossoutfile = ajAcdGetOutfile("outfile");
emboss_openfile(embossoutfile, &outfile, &outfilename);
if(factorrequest) {
embossoutfact = ajAcdGetOutfile("outfactorfile");
emboss_openfile(embossoutfact, &outfactfile, &outfactname);
}
if(ancstrrequest) {
embossoutanc = ajAcdGetOutfile("outancfile");
emboss_openfile(embossoutanc, &outancfile, &outfactname);
}
} /* emboss_getoptions */
void readtree()
{
/* Reads a single character-state tree; puts adjacent symbol
pairs into array 'pairs' */
int npairs = 0;
const char* cp;
cp = ajStrGetPtr(rdline);
while (*cp && isspace((int)*cp))
cp++;
while (*cp && isdigit((int)*cp))
cp++;
while (*cp) {
while (*cp && isspace((int)*cp))
cp++;
ch = *cp++;
npairs++;
pair[npairs - 1][0] = ch;
while (*cp && isspace((int)*cp))
cp++;
ch = *cp++;
if (!(*cp) || (ch != factchar)) {
printf("\n\nERROR: Character %d: bad character state tree format1\n\n",
(int)(cp - ajStrGetPtr(rdline)));
printf("\n\nch: %c\n", ch);
embExitBad();
}
while (*cp && isspace((int)*cp))
cp++;
ch = *cp++;
pair[npairs - 1][1] = ch;
while (*cp && isspace((int)*cp))
cp++;
if (pair[npairs - 1][1] == ' ')
{
printf("\n\nERROR: Character %d: bad character state tree format2\n\n",
(int)(cp - ajStrGetPtr(rdline)));
embExitBad();
}
while (*cp && isspace((int)*cp))
cp++;
}
} /* readtree */
void attachnodes(statenode *poynter, Char *otherone)
{
/* Makes linked list of all nodes to which passed node is
ancestral. First such node is 'descendant'; second
such node is 'sibling' of first; third such node is
sibling of second; etc. */
statenode *linker, *ptr;
long i, j, k;
linker = poynter;
for (i = 0; i < (npairs); i++) {
for (j = 1; j <= 2; j++) {
if (poynter->state == pair[i][j - 1]) {
if (j == 1)
*otherone = pair[i][1];
else
*otherone = pair[i][0];
if (*otherone != '.' && *otherone != poynter->ancstr->state) {
k = offset + 1;
while (*otherone != symbarray[k - 1])
k++;
if (nodes[k - offset - 1] != NULL)
embExitBad();
ptr = (statenode *)Malloc(sizeof(statenode));
ptr->ancstr = poynter;
ptr->descendant = NULL;
ptr->sibling = NULL;
ptr->state = *otherone;
if (linker == poynter) /* If not first */
poynter->descendant = ptr; /* If first */
else
linker->sibling = ptr;
nodes[k - offset - 1] = ptr;
/* Save pntr to node */
linker = ptr;
}
}
}
}
} /* attachnodes */
void maketree(statenode *poynter, Char *otherone)
{
/* Recursively attach nodes */
if (poynter == NULL)
return;
attachnodes(poynter, otherone);
maketree(poynter->descendant, otherone);
maketree(poynter->sibling, otherone);
} /* maketree */
void construct()
{
/* Puts tree together from array 'pairs' */
Char rootstate;
long i, j, k;
boolean done;
statenode *poynter;
char otherone;
rooted = false;
ancsymbol[charindex - 1] = '?';
rootstate = pair[0][0];
nstates = 0;
for (i = 0; i < (npairs); i++) {
for (j = 1; j <= 2; j++) {
k = 1;
done = false;
while (!done) {
if (k > nstates) {
done = true;
break;
}
if (pair[i][j - 1] == symbarray[offset + k - 1])
done = true;
else
k++;
}
if (k > nstates) {
if (pair[i][j - 1] == '.') {
if (rooted)
embExitBad();
rooted = true;
ancsymbol[charindex - 1] = '0';
if (j == 1)
rootstate = pair[i][1];
else
rootstate = pair[i][0];
} else {
nstates++;
symbarray[offset + nstates - 1] = pair[i][j - 1];
}
}
}
}
if ((rooted && nstates != npairs) ||
(!rooted && nstates != npairs + 1))
embExitBad();
root = (statenode *)Malloc(sizeof(statenode));
root->state = ' ';
root->descendant = (statenode *)Malloc(sizeof(statenode));
root->descendant->ancstr = root;
root = root->descendant;
root->descendant = NULL;
root->sibling = NULL;
root->state = rootstate;
for (i = 0; i < (nstates); i++)
nodes[i] = NULL;
i = 1;
while (symbarray[offset + i - 1] != rootstate)
i++;
nodes[i - 1] = root;
maketree(root, &otherone);
for (i = 0; i < (nstates); i++) {
if (nodes[i] != root) {
if (nodes[i] == NULL){
printf(
"\n\nERROR: Character %ld: invalid character state tree description\n",
charnumber);
embExitBad();}
else {
poynter = nodes[i]->ancstr;
while (poynter != root && poynter != nodes[i])
poynter = poynter->ancstr;
if (poynter != root){
printf(
"ERROR: Character %ld: invalid character state tree description\n\n",
charnumber);
embExitBad();}
}
}
}
} /* construct */
void numberedges(statenode *poynter, long *edgenum)
{
/* Assign to each node a number for the edge below it.
The root is zero */
if (poynter == NULL)
return;
poynter->edge = *edgenum;
(*edgenum)++;
numberedges(poynter->descendant, edgenum);
numberedges(poynter->sibling, edgenum);
} /* numberedges */
void factortree()
{
/* Generate the string of 0's and 1's that will be
substituted for each symbol of the multistate char. */
long i, j, place, factoroffset;
statenode *poynter;
long edgenum=0;
numberedges(root, &edgenum);
factoroffset = offset + nstates;
for (i = 0; i < (nstates); i++) {
place = factoroffset + (nstates - 1) * i;
for (j = place; j <= (place + nstates - 2); j++)
symbarray[j] = '0';
poynter = nodes[i];
while (poynter != root) {
symbarray[place + poynter->edge - 1] = '1';
poynter = poynter->ancstr;
}
}
} /* factortree */
void dotrees()
{
/* Process character-state trees */
long lastchar;
ajint ival=0;
charindex = 0;
lastchar = 0;
offset = 0;
charnumber = 0;
ajReadlineTrim(inputfile, &rdline);
if(ajFmtScanS(rdline, "%d", &ival) != 1) {
printf("Invalid input file!\n");
embExitBad();
}
charnumber = ival;
while (charnumber < 999) {
if (charnumber < lastchar) {
printf("\n\nERROR: Character state tree");
printf(" for character %ld: out of order\n\n", charnumber);
embExitBad();
}
charindex++;
lastindex = charindex;
readtree(); /* Process character-state tree */
if (npairs > 0) {
construct(); /* Link tree together */
factortree();
} else {
nstates = 0;
ancsymbol[charindex - 1] = '?';
}
lastchar = charnumber;
charnum[charindex - 1] = charnumber;
chstart[charindex - 1] = offset;
numstates[charindex - 1] = nstates;
offset += nstates * nstates;
ajReadlineTrim(inputfile, &rdline);
ajFmtScanS(rdline, "%d", &ival);
charnumber = ival;
}
/* each multistate character */
/* symbol */
} /* dotrees */
void writech(Char ch, long *chposition, FILE *outauxfile)
{
/* Writes a single character to output */
if (*chposition > maxoutput) {
putc('\n', outauxfile);
*chposition = 1;
}
putc(ch, outauxfile);
(*chposition)++;
} /* writech */
void writefactors(long *chposition)
{ /* Writes 'FACTORS' line */
long i, charindex;
Char symbol;
*chposition = 11;
symbol = '-';
for (charindex = 0; charindex < (lastindex); charindex++) {
if (symbol == '-')
symbol = '+';
else
symbol = '-';
if (numstates[charindex] == 0)
writech(symbol, chposition, outfactfile);
else {
for (i = 1; i < (numstates[charindex]); i++)
writech(symbol, chposition, outfactfile);
}
}
putc('\n', outfactfile);
} /* writefactors */
void writeancestor(long *chposition)
{
/* Writes 'ANCESTOR' line */
long i, charindex;
charindex = 1;
while (ancsymbol[charindex - 1] == '?')
charindex++;
if (charindex > lastindex)
return;
*chposition = 11;
for (charindex = 0; charindex < (lastindex); charindex++) {
if (numstates[charindex] == 0)
writech(ancsymbol[charindex], chposition, outancfile);
else {
for (i = 1; i < (numstates[charindex]); i++)
writech(ancsymbol[charindex], chposition, outancfile);
}
}
putc('\n', outancfile);
} /* writeancestor */
void doeu(long *chposition, long eu)
{
/* Writes factored data for a single species */
long i, charindex, place;
Char *multichar;
const char* cp;
ajReadlineTrim(inputfile, &rdline);
cp = ajStrGetPtr(rdline);
for (i = 1; i <= nmlngth; i++) {
ch = *cp++;
putc(ch, outfile);
if ((ch == '(') || (ch == ')') || (ch == ':')
|| (ch == ',') || (ch == ';') || (ch == '[')
|| (ch == ']')) {
printf(
"\n\nERROR: Species name may not contain characters ( ) : ; , [ ] \n");
printf(" In name of species number %ld there is character %c\n\n",
i+1, ch);
embExitBad();
}
}
multichar = (Char *)Malloc(nchars*sizeof(Char));
*chposition = 11;
for (i = 0; i < (nchars); i++) {
ch = *cp++;
while (isspace((int)ch)) {
ch = *cp++;
if (!*cp)
{
ajReadlineTrim(inputfile, &rdline);
cp = ajStrGetPtr(rdline);
ch = *cp++;
}
}
multichar[i] = ch;
}
for (charindex = 0; charindex < (lastindex); charindex++) {
if (numstates[charindex] == 0)
writech(multichar[charnum[charindex] - 1], chposition, outfile);
else {
i = 1;
while (symbarray[chstart[charindex] + i - 1] !=
multichar[charnum[charindex] - 1] && i <= numstates[charindex])
i++;
if (i > numstates[charindex]) {
if( multichar[charnum[charindex] - 1] == unkchar){
for (i = 1; i < (numstates[charindex]); i++)
writech('?', chposition, outfile);
} else {
putc('\n', outfile);
printf("\n\nERROR: In species %ld, multistate character %ld: ",
eu, charnum[charindex]);
printf("'%c' is not a documented state\n\n",
multichar[charnum[charindex] - 1]);
embExitBad();
}
} else {
place = chstart[charindex] + numstates[charindex] +
(numstates[charindex] - 1) * (i - 1);
for (i = 0; i <= (numstates[charindex] - 2); i++)
writech(symbarray[place + i], chposition, outfile);
}
}
}
putc('\n', outfile);
free(multichar);
} /* doeu */
void dodatamatrix()
{
/* Reads species information and write factored data set */
long charindex, totalfactors, eu, chposition;
totalfactors = 0;
for (charindex = 0; charindex < (lastindex); charindex++) {
if (numstates[charindex] == 0)
totalfactors++;
else
totalfactors += numstates[charindex] - 1;
}
if (rooted && ancstrrequest)
fprintf(outfile, "%5ld %4ld\n", neus + 1, totalfactors);
else
fprintf(outfile, "%5ld %4ld\n", neus, totalfactors);
if (factorrequest)
writefactors(&chposition);
if (ancstrrequest)
writeancestor(&chposition);
eu = 1;
while (eu <= neus) {
eu++;
doeu(&chposition, eu);
}
if (progress)
printf("\nData matrix written on file \"%s\"\n\n", outfilename);
} /* dodatamatrix */
int main(int argc, Char *argv[])
{
#ifdef MAC
argc = 1; /* macsetup("Factor",""); */
argv[0] = "Factor";
#endif
init(argc,argv);
emboss_getoptions("ffactor", argc, argv);
ajReadlineTrim(inputfile, &rdline);
sscanf(ajStrGetPtr(rdline), "%ld%ld", &neus, &nchars);
charnum = (long *)Malloc(nchars*sizeof(long));
chstart = (long *)Malloc(nchars*sizeof(long));
numstates = (long *)Malloc(nchars*sizeof(long));
ancsymbol = (Char *)Malloc(nchars*sizeof(Char));
dotrees(); /* Read and factor character-state trees */
dodatamatrix();
ajFileClose(&inputfile);
FClose(outfile);
#ifdef MAC
fixmacfile(outfilename);
#endif
printf("Done.\n\n");
#ifdef WIN32
phyRestoreConsoleAttributes();
#endif
embExit();
return 0;
} /* factor */
PHYLIPNEW-3.69.650/src/seqboot.c 0000664 0001750 0001750 00000076126 11616234204 012710 0000000 0000000 /* version 3.6. (c) Copyright 1993-2005 by the University of Washington.
Written by Joseph Felsenstein, Akiko Fuseki, Sean Lamont, Andrew Keeffe,
and Doug Buxton.
Permission is granted to copy and use this program provided no fee is
charged for it and provided that this copyright notice is not removed. */
#include "phylip.h"
#include "seq.h"
typedef enum {
seqs, morphology, restsites, genefreqs
} datatype;
typedef enum {
dna, rna, protein
} seqtype;
AjPSeqset seqset = NULL;
AjPPhyloProp phyloratecat = NULL;
AjPPhyloProp phyloweights = NULL;
#ifndef OLDC
/* function prototypes */
//void getoptions(void);
void emboss_getoptions(char *pgm, int argc, char *argv[]);
void seqboot_inputnumbersseq(AjPSeqset);
void inputoptions(void);
char **matrix_char_new(long rows, long cols);
void matrix_char_delete(char **mat, long rows);
double **matrix_double_new(long rows, long cols);
void matrix_double_delete(double **mat, long rows);
void seqboot_inputdataseq(AjPSeqset);
void allocrest(void);
void freerest(void);
void allocnew(void);
void freenew(void);
void allocnewer(long newergroups, long newersites);
void doinput(int argc, Char *argv[]);
void bootweights(void);
void permute_vec(long *a, long n);
void sppermute(long);
void charpermute(long, long);
void writedata(void);
void writeweights(void);
void writecategories(void);
void writeauxdata(steptr, FILE*);
void writefactors(void);
void bootwrite(void);
void seqboot_inputaux(steptr, FILE*);
void freenewer(void);
/* function prototypes */
#endif
/*** Config vars ***/
/* Mutually exclusive booleans for boostrap type */
boolean bootstrap, jackknife;
boolean permute; /* permute char order */
boolean ild; /* permute species for each char */
boolean lockhart; /* permute chars within species */
boolean rewrite;
boolean factors = false; /* Use factors (only with morph data) */
/* Bootstrap/jackknife sample frequency */
boolean regular = true; /* Use 50% sampling with bootstrap/jackknife */
double fracsample = 0.5; /* ...or user-defined sample freq, [0..inf) */
/* Output format: mutually exclusive, none indicates PHYLIP */
boolean xml = false;
boolean nexus = false;
boolean weights = false;/* Read weights file */
boolean categories = false;/* Use categories (permuted with dataset) */
boolean enzymes;
boolean all; /* All alleles present in infile? */
boolean justwts = false; /* Write boot'd/jack'd weights, no datasets */
boolean mixture;
boolean ancvar;
boolean progress = true; /* Enable progress indications */
boolean firstrep; /* TODO Must this be global? */
longer seed;
/* Filehandles and paths */
/* Usual suspects declared in phylip.c/h */
FILE *outcatfile, *outweightfile, *outmixfile, *outancfile, *outfactfile;
Char infilename[FNMLNGTH], catfilename[FNMLNGTH], weightfilename[FNMLNGTH], mixfilename[FNMLNGTH], ancfilename[FNMLNGTH], factfilename[FNMLNGTH];
const char* outfilename;
AjPFile embossoutfile;
const char* outweightfilename;
AjPFile embossoutweightfile;
const char* outmixfilename;
AjPFile embossoutmixfile;
const char* outancfilename;
AjPFile embossoutancfile;
const char* outcatfilename;
AjPFile embossoutcatfile;
const char* outfactfilename;
AjPFile embossoutfactfile;
long sites, loci, maxalleles, groups,
nenzymes, reps, ws, blocksize, categs, maxnewsites;
datatype data;
seqtype seq;
steptr oldweight, where, how_many, mixdata, ancdata;
/* Original dataset */
/* [0..spp-1][0..sites-1] */
Char **nodep = NULL; /* molecular or morph data */
double **nodef = NULL; /* gene freqs */
Char *factor = NULL; /* factor[sites] - direct read-in of factors file */
long *factorr = NULL; /* [0..sites-1] => nondecreasing [1..groups] */
long *alleles = NULL;
/* Mapping with read-in weights eliminated
* Allocated once in allocnew() */
long newsites;
long newgroups;
long *newwhere = NULL; /* Map [0..newgroups-1] => [1..newsites] */
long *newhowmany = NULL; /* Number of chars for each [0..newgroups-1] */
/* Mapping with bootstrapped weights applied */
/* (re)allocated by allocnewer() */
long newersites, newergroups;
long *newerfactor = NULL; /* Map [0..newersites-1] => [1..newergroups] */
long *newerwhere = NULL; /* Map [0..newergroups-1] => [1..newersites] */
long *newerhowmany = NULL; /* Number of chars for each [0..newergroups-1] */
long **charorder = NULL; /* Permutation [0..spp-1][0..newergroups-1] */
long **sppord = NULL; /* Permutation [0..newergroups-1][0..spp-1] */
void emboss_getoptions(char *pgm, int argc, char *argv[])
{
AjPStr test = NULL;
AjPStr outputformat = NULL;
AjPStr typeofseq = NULL;
AjPStr justweights = NULL;
AjBool rewrite = false;
long inseed, inseed0;
data = seqs;
seq = dna;
bootstrap = false;
jackknife = false;
permute = false;
ild = false;
lockhart = false;
blocksize = 1;
regular = true;
fracsample = 1.0;
all = false;
reps = 100;
weights = false;
mixture = false;
ancvar = false;
categories = false;
justwts = false;
printdata = false;
dotdiff = true;
progress = true;
interleaved = true;
xml = false;
nexus = false;
factors = false;
enzymes = false;
embInitPV(pgm, argc, argv, "PHYLIPNEW",VERSION);
seqset = ajAcdGetSeqset("sequence");
test = ajAcdGetListSingle("test");
if(ajStrMatchC(test, "b")) {
bootstrap = true;
regular = ajAcdGetToggle("regular");
if(regular) fracsample = 1.0;
else {
fracsample = ajAcdGetFloat("fracsample");
fracsample = fracsample/100.0;
}
blocksize = ajAcdGetInt("blocksize");
}
else if(ajStrMatchC(test, "j")) {
jackknife = true;
regular = ajAcdGetToggle("regular");
if(regular) fracsample = 0.5;
else {
fracsample = ajAcdGetFloat("fracsample");
fracsample = fracsample/100.0;
}
}
else if(ajStrMatchC(test, "c")) permute = true;
else if(ajStrMatchC(test, "o")) ild = true;
else if(ajStrMatchC(test, "s")) lockhart = true;
else if(ajStrMatchC(test, "r")) rewrite = true;
if(rewrite) {
outputformat = ajAcdGetListSingle("rewriteformat");
if(ajStrMatchC(outputformat, "n")) nexus = true;
else if(ajStrMatchC(outputformat, "x")) xml = true;
if( (nexus) || (xml) ) {
typeofseq = ajAcdGetListSingle("seqtype");
if(ajStrMatchC(typeofseq, "d")) seq = dna;
else if(ajStrMatchC(typeofseq, "r")) seq = rna;
else if(ajStrMatchC(typeofseq, "p")) seq = protein;
}
}
else{
reps = ajAcdGetInt("reps");
inseed = ajAcdGetInt("seed");
emboss_initseed(inseed, &inseed0, seed);
if(jackknife || bootstrap || permute) {
phyloweights = ajAcdGetProperties("weights");
if(phyloweights) weights = true;
phyloratecat = ajAcdGetProperties("categories");
if(phyloratecat) categories = true;
if(!permute) {
justweights = ajAcdGetListSingle("justweights");
if(ajStrMatchC(justweights, "j")) justwts = true;
}
}
}
printdata = ajAcdGetBoolean("printdata");
if(printdata) dotdiff = ajAcdGetBoolean("dotdiff");
progress = ajAcdGetBoolean("progress");
embossoutfile = ajAcdGetOutfile("outfile");
emboss_openfile(embossoutfile, &outfile, &outfilename);
} /* emboss_getoptions */
void seqboot_inputnumbersseq(AjPSeqset seqset)
{
/* read numbers of species and of sites */
spp = ajSeqsetGetSize(seqset);
sites = ajSeqsetGetLen(seqset);
loci = sites;
maxalleles = 1;
} /* seqboot_inputnumbersseq */
void inputoptions()
{
/* input the information on the options */
long weightsum, maxfactsize, i, j, k, l, m;
if (data == genefreqs) {
k = 0;
l = 0;
for (i = 0; i < (loci); i++) {
m = alleles[i];
k++;
for (j = 1; j <= m; j++) {
l++;
factorr[l - 1] = k;
}
}
} else {
for (i = 1; i <= (sites); i++)
factorr[i - 1] = i;
}
for (i = 0; i < (sites); i++)
oldweight[i] = 1;
if (weights)
inputweightsstr2(phyloweights->Str[0],0, sites, &weightsum, oldweight, &weights, "seqboot");
if (factors && printdata) {
for(i = 0; i < sites; i++)
factor[i] = (char)('0' + (factorr[i]%10));
printfactors(outfile, sites, factor, " (least significant digit)");
}
if (weights && printdata)
printweights(outfile, 0, sites, oldweight, "Sites");
for (i = 0; i < (loci); i++)
how_many[i] = 0;
for (i = 0; i < (loci); i++)
where[i] = 0;
for (i = 1; i <= (sites); i++) {
how_many[factorr[i - 1] - 1]++;
if (where[factorr[i - 1] - 1] == 0)
where[factorr[i - 1] - 1] = i;
}
groups = factorr[sites - 1];
newgroups = 0;
newsites = 0;
maxfactsize = 0;
for(i = 0 ; i < loci ; i++){
if(how_many[i] > maxfactsize){
maxfactsize = how_many[i];
}
}
maxnewsites = groups * maxfactsize;
allocnew();
for (i = 0; i < groups; i++) {
if (oldweight[where[i] - 1] > 0) {
newgroups++;
newsites += how_many[i];
newwhere[newgroups - 1] = where[i];
newhowmany[newgroups - 1] = how_many[i];
}
}
} /* inputoptions */
char **matrix_char_new(long rows, long cols)
{
char **mat;
long i;
assert(rows > 0); assert(cols > 0);
mat = (char **)Malloc(rows*sizeof(char *));
for (i = 0; i < rows; i++)
mat[i] = (char *)Malloc(cols*sizeof(char));
return mat;
}
void matrix_char_delete(char **mat, long rows)
{
long i;
assert(mat != NULL);
for (i = 0; i < rows; i++)
free(mat[i]);
free(mat);
}
double **matrix_double_new(long rows, long cols)
{
double **mat;
long i;
assert(rows > 0); assert(cols > 0);
mat = (double **)Malloc(rows*sizeof(double *));
for (i = 0; i < rows; i++)
mat[i] = (double *)Malloc(cols*sizeof(double));
return mat;
}
void matrix_double_delete(double **mat, long rows)
{
long i;
assert(mat != NULL);
for (i = 0; i < rows; i++)
free(mat[i]);
free(mat);
}
void seqboot_inputdataseq(AjPSeqset seqset)
{
/* input the names and sequences for each species */
long i, j, k, l, m, n;
Char charstate;
boolean allread, done;
const AjPStr str;
nodep = matrix_char_new(spp, sites);
j = nmlngth + (sites + (sites - 1) / 10) / 2 - 5;
if (j < nmlngth - 1)
j = nmlngth - 1;
if (j > 37)
j = 37;
if (printdata) {
fprintf(outfile, "\nBootstrapping algorithm, version %s\n\n\n",VERSION);
if (bootstrap) {
if (blocksize > 1) {
if (regular)
fprintf(outfile, "Block-bootstrap with block size %ld\n\n", blocksize);
else
fprintf(outfile, "Partial (%2.0f%%) block-bootstrap with block size %ld\n\n",
100*fracsample, blocksize);
} else {
if (regular)
fprintf(outfile, "Bootstrap\n\n");
else
fprintf(outfile, "Partial (%2.0f%%) bootstrap\n\n", 100*fracsample);
}
} else {
if (jackknife) {
if (regular)
fprintf(outfile, "Delete-half Jackknife\n\n");
else
fprintf(outfile, "Delete-%2.0f%% Jackknife\n\n", 100*(1.0-fracsample));
} else {
if (permute) {
fprintf(outfile, "Species order permuted separately for each");
fprintf(outfile, " site\n\n");
}
else {
if (ild) {
fprintf(outfile, "Site");
fprintf(outfile, " order permuted\n\n");
} else {
if (lockhart)
fprintf(outfile, "Site");
fprintf(outfile, " order permuted separately for each species\n\n");
}
}
}
}
fprintf(outfile, "%3ld species, ", spp);
fprintf(outfile, "%3ld sites\n\n", sites);
fprintf(outfile, "Name");
for (i = 1; i <= j; i++)
putc(' ', outfile);
fprintf(outfile, "Data\n");
fprintf(outfile, "----");
for (i = 1; i <= j; i++)
putc(' ', outfile);
fprintf(outfile, "----\n\n");
}
allread = false;
while (!allread) {
i = 1;
while (i <= spp) {
initnameseq(seqset, i-1);
str = ajSeqGetSeqS(ajSeqsetGetseqSeq(seqset, i-1));
j=0;
done = false;
while (!done) {
while (j < sites ) {
charstate = ajStrGetCharPos(str, j);
uppercase(&charstate);
j++;
if (charstate == '.')
charstate = nodep[0][j-1];
nodep[i-1][j-1] = charstate;
}
if (j == sites)
done = true;
}
i++;
}
allread = (i > spp);
}
if (!printdata)
return;
m = (sites - 1) / 60 + 1;
for (i = 1; i <= m; i++) {
for (j = 0; j < spp; j++) {
for (k = 0; k < nmlngth; k++)
putc(nayme[j][k], outfile);
fprintf(outfile, " ");
l = i * 60;
if (l > sites)
l = sites;
n = (i - 1) * 60;
for (k = n; k < l; k++) {
if (j + 1 > 1 && nodep[j][k] == nodep[0][k])
charstate = '.';
else
charstate = nodep[j][k];
putc(charstate, outfile);
if ((k + 1) % 10 == 0 && (k + 1) % 60 != 0)
putc(' ', outfile);
}
putc('\n', outfile);
}
putc('\n', outfile);
}
putc('\n', outfile);
} /* seqboot_inputdataseq */
void allocrest()
{ /* allocate memory for bookkeeping arrays */
oldweight = (steptr)Malloc(sites*sizeof(long));
weight = (steptr)Malloc(sites*sizeof(long));
if (categories)
category = (steptr)Malloc(sites*sizeof(long));
if (mixture)
mixdata = (steptr)Malloc(sites*sizeof(long));
if (ancvar)
ancdata = (steptr)Malloc(sites*sizeof(long));
where = (steptr)Malloc(loci*sizeof(long));
how_many = (steptr)Malloc(loci*sizeof(long));
factor = (Char *)Malloc(sites*sizeof(Char));
factorr = (steptr)Malloc(sites*sizeof(long));
nayme = (naym *)Malloc(spp*sizeof(naym));
} /* allocrest */
void freerest()
{
/* Free bookkeeping arrays */
if (alleles)
free(alleles);
free(oldweight);
free(weight);
if (categories)
free(category);
if (mixture)
free(mixdata);
if (ancvar)
free(ancdata);
free(where);
free(how_many);
free(factor);
free(factorr);
free(nayme);
}
void allocnew(void)
{ /* allocate memory for arrays that depend on the lenght of the
output sequence*/
/* Only call this function once */
assert(newwhere == NULL && newhowmany == NULL);
newwhere = (steptr)Malloc(loci*sizeof(long));
newhowmany = (steptr)Malloc(loci*sizeof(long));
}
void freenew(void)
{ /* free arrays allocated by allocnew() */
/* Only call this function once */
assert(newwhere != NULL);
assert(newhowmany != NULL);
free(newwhere);
free(newhowmany);
}
void allocnewer(long newergroups, long newersites)
{ /* allocate memory for arrays that depend on the length of the bootstrapped
output sequence */
/* Assumes that spp remains constant */
static long curnewergroups = 0;
static long curnewersites = 0;
long i;
if (newerwhere != NULL) {
if (newergroups > curnewergroups) {
free(newerwhere);
free(newerhowmany);
for (i = 0; i < spp; i++)
free(charorder[i]);
newerwhere = NULL;
}
if (newersites > curnewersites) {
free(newerfactor);
newerfactor = NULL;
}
}
if (charorder == NULL)
charorder = (steptr *)Malloc(spp*sizeof(steptr));
/* Malloc() will fail if either is 0, so add a dummy element */
if (newergroups == 0)
newergroups++;
if (newersites == 0)
newersites++;
if (newerwhere == NULL) {
newerwhere = (steptr)Malloc(newergroups*sizeof(long));
newerhowmany = (steptr)Malloc(newergroups*sizeof(long));
for (i = 0; i < spp; i++)
charorder[i] = (steptr)Malloc(newergroups*sizeof(long));
curnewergroups = newergroups;
}
if (newerfactor == NULL) {
newerfactor = (steptr)Malloc(newersites*sizeof(long));
curnewersites = newersites;
}
}
void freenewer()
{
/* Free memory allocated by allocnewer() */
/* spp must be the same as when allocnewer was called */
long i;
if (newerwhere) {
free(newerwhere);
free(newerhowmany);
free(newerfactor);
for (i = 0; i < spp; i++)
free(charorder[i]);
free(charorder);
}
}
void doinput(int argc, Char *argv[])
{ /* reads the input data */
seqboot_inputnumbersseq(seqset);
allocrest();
inputoptions();
seqboot_inputdataseq(seqset);
} /* doinput */
void bootweights()
{ /* sets up weights by resampling data */
long i, j, k, blocks;
double p, q, r;
long grp = 0, site = 0;
ws = newgroups;
for (i = 0; i < (ws); i++)
weight[i] = 0;
if (jackknife) {
if (fabs(newgroups*fracsample - (long)(newgroups*fracsample+0.5))
> 0.00001) {
if (randum(seed)
< (newgroups*fracsample - (long)(newgroups*fracsample))
/((long)(newgroups*fracsample+1.0)-(long)(newgroups*fracsample)))
q = (long)(newgroups*fracsample)+1;
else
q = (long)(newgroups*fracsample);
} else
q = (long)(newgroups*fracsample+0.5);
r = newgroups;
p = q / r;
ws = 0;
for (i = 0; i < (newgroups); i++) {
if (randum(seed) < p) {
weight[i]++;
ws++;
q--;
}
r--;
if (i + 1 < newgroups)
p = q / r;
}
} else if (permute) {
for (i = 0; i < (newgroups); i++)
weight[i] = 1;
} else if (bootstrap) {
blocks = fracsample * newgroups / blocksize;
for (i = 1; i <= (blocks); i++) {
j = (long)(newgroups * randum(seed)) + 1;
for (k = 0; k < blocksize; k++) {
weight[j - 1]++;
j++;
if (j > newgroups)
j = 1;
}
}
} else /* case of rewriting data */
for (i = 0; i < (newgroups); i++)
weight[i] = 1;
/* Count number of replicated groups */
newergroups = 0;
newersites = 0;
for (i = 0; i < newgroups; i++) {
newergroups += weight[i];
newersites += newhowmany[i] * weight[i];
}
if (newergroups < 1) {
fprintf(stdout, "ERROR: sampling frequency or number of sites is too small\n");
exxit(-1);
}
/* reallocate "newer" arrays, sized by output groups:
* newerfactor, newerwhere, newerhowmany, and charorder */
allocnewer(newergroups, newersites);
/* Replicate each group i weight[i] times */
grp = 0;
site = 0;
for (i = 0; i < newgroups; i++) {
for (j = 0; j < weight[i]; j++) {
for (k = 0; k < newhowmany[i]; k++) {
newerfactor[site] = grp + 1;
site++;
}
newerwhere[grp] = newwhere[i];
newerhowmany[grp] = newhowmany[i];
grp++;
}
}
} /* bootweights */
void permute_vec(long *a, long n)
{
long i, j, k;
for (i = 1; i < n; i++) {
k = (long)((i+1) * randum(seed));
j = a[i];
a[i] = a[k];
a[k] = j;
}
}
void sppermute(long n)
{ /* permute the species order as given in array sppord */
permute_vec(sppord[n-1], spp);
} /* sppermute */
void charpermute(long m, long n)
{ /* permute the n+1 characters of species m+1 */
permute_vec(charorder[m], n);
} /* charpermute */
void writedata()
{
/* write out one set of bootstrapped sequences */
long i, j, k, l, m, n, n2=0;
double x;
Char charstate;
sppord = (long **)Malloc(newergroups*sizeof(long *));
for (i = 0; i < (newergroups); i++)
sppord[i] = (long *)Malloc(spp*sizeof(long));
for (j = 1; j <= spp; j++)
sppord[0][j - 1] = j;
for (i = 1; i < newergroups; i++) {
for (j = 1; j <= (spp); j++)
sppord[i][j - 1] = sppord[i - 1][j - 1];
}
if (!justwts || permute) {
if (data == restsites && enzymes)
fprintf(outfile, "%5ld %5ld% 4ld\n", spp, newergroups, nenzymes);
else if (data == genefreqs)
fprintf(outfile, "%5ld %5ld\n", spp, newergroups);
else {
if ((data == seqs) && rewrite && xml)
fprintf(outfile, "\n");
else
if (rewrite && nexus) {
fprintf(outfile, "#NEXUS\n");
fprintf(outfile, "BEGIN DATA;\n");
fprintf(outfile, " DIMENSIONS NTAX=%ld NCHAR=%ld;\n",
spp, newersites);
fprintf(outfile, " FORMAT");
if (interleaved)
fprintf(outfile, " interleave=yes");
else
fprintf(outfile, " interleave=no");
fprintf(outfile, " DATATYPE=");
if (data == seqs) {
switch (seq) {
case (dna): fprintf(outfile, "DNA missing=N gap=-"); break;
case (rna): fprintf(outfile, "RNA missing=N gap=-"); break;
case (protein):
fprintf(outfile, "protein missing=? gap=-");
break;
}
}
if (data == morphology)
fprintf(outfile, "STANDARD");
fprintf(outfile, ";\n MATRIX\n");
}
else fprintf(outfile, "%5ld %5ld\n", spp, newersites);
}
if (data == genefreqs) {
for (i = 0; i < (newergroups); i++)
fprintf(outfile, " %3ld", alleles[factorr[newerwhere[i] - 1] - 1]);
putc('\n', outfile);
}
}
l = 1;
if ((!(bootstrap || jackknife || permute || ild || lockhart | nexus))
&& ((data == seqs) || (data == restsites))) {
interleaved = !interleaved;
if (!(bootstrap || jackknife || permute || ild || lockhart) && xml)
interleaved = false;
}
m = interleaved ? 60 : newergroups;
do {
if (m > newergroups)
m = newergroups;
for (j = 0; j < spp; j++) {
n = 0;
if ((l == 1) || (interleaved && nexus)) {
if (rewrite && xml) {
fprintf(outfile, " \n");
fprintf(outfile, " ");
}
n2 = nmlngth;
if (rewrite && (xml || nexus)) {
while (nayme[j][n2-1] == ' ')
n2--;
}
if (nexus)
fprintf(outfile, " ");
for (k = 0; k < n2; k++)
if (nexus && (nayme[j][k] == ' ') && (k < n2))
putc('_', outfile);
else
putc(nayme[j][k], outfile);
if (rewrite && xml)
fprintf(outfile, "\n ");
} else {
if (rewrite && xml) {
fprintf(outfile, " ");
}
}
if (!xml) {
for (k = 0; k < nmlngth-n2; k++)
fprintf(outfile, " ");
fprintf(outfile, " ");
}
for (k = l - 1; k < m; k++) {
if (permute && j + 1 == 1)
sppermute(newerfactor[n]); /* we can assume chars not permuted */
for (n2 = -1; n2 <= (newerhowmany[charorder[j][k]] - 2); n2++) {
n++;
if (data == genefreqs) {
if (n > 1 && (n & 7) == 1)
fprintf(outfile, "\n ");
x = nodef[sppord[charorder[j][k]][j] - 1]
[newerwhere[charorder[j][k]] + n2];
fprintf(outfile, "%8.5f", x);
} else {
if (rewrite && xml && (n > 1) && (n % 60 == 1))
fprintf(outfile, "\n ");
else if (!nexus && !interleaved && (n > 1) && (n % 60 == 1))
fprintf(outfile, "\n ");
charstate = nodep[sppord[charorder[j][k]][j] - 1]
[newerwhere[charorder[j][k]] + n2];
putc(charstate, outfile);
if (n % 10 == 0 && n % 60 != 0)
putc(' ', outfile);
}
}
}
if (rewrite && xml) {
fprintf(outfile, "\n \n");
}
putc('\n', outfile);
}
if (interleaved) {
if ((m <= newersites) && (newersites > 60))
putc('\n', outfile);
l += 60;
m += 60;
}
} while (interleaved && l <= newersites);
if ((data == seqs) &&
(!(bootstrap || jackknife || permute || ild || lockhart) && xml))
fprintf(outfile, "\n");
if (!(bootstrap || jackknife || permute || ild || lockhart) && nexus)
fprintf(outfile, " ;\nEND;\n");
for (i = 0; i < (newergroups); i++)
free(sppord[i]);
free(sppord);
} /* writedata */
void writeweights()
{ /* write out one set of post-bootstrapping weights */
long j, k, l, m, n, o;
j = 0;
l = 1;
if (interleaved)
m = 60;
else
m = sites;
do {
if(m > sites)
m = sites;
n = 0;
for (k = l - 1; k < m; k++) {
for(o = 0 ; o < how_many[k] ; o++){
if(oldweight[k]==0){
fprintf(outweightfile, "0");
j++;
}
else{
if (weight[k-j] < 10)
fprintf(outweightfile, "%c", (char)('0'+weight[k-j]));
else
fprintf(outweightfile, "%c", (char)('A'+weight[k-j]-10));
n++;
if (!interleaved && n > 1 && n % 60 == 1) {
fprintf(outweightfile, "\n");
if (n % 10 == 0 && n % 60 != 0)
putc(' ', outweightfile);
}
}
}
}
putc('\n', outweightfile);
if (interleaved) {
l += 60;
m += 60;
}
} while (interleaved && l <= sites);
} /* writeweights */
void writecategories()
{
/* write out categories for the bootstrapped sequences */
long k, l, m, n, n2;
Char charstate;
if(justwts){
if (interleaved)
m = 60;
else
m = sites;
l=1;
do {
if(m > sites)
m = sites;
n=0;
for(k=l-1 ; k < m ; k++){
n++;
if (!interleaved && n > 1 && n % 60 == 1)
fprintf(outcatfile, "\n ");
charstate = '0' + category[k];
putc(charstate, outcatfile);
}
if (interleaved) {
l += 60;
m += 60;
}
}while(interleaved && l <= sites);
fprintf(outcatfile, "\n");
return;
}
l = 1;
if (interleaved)
m = 60;
else
m = newergroups;
do {
if (m > newergroups)
m = newergroups;
n = 0;
for (k = l - 1; k < m; k++) {
for (n2 = -1; n2 <= (newerhowmany[k] - 2); n2++) {
n++;
if (!interleaved && n > 1 && n % 60 == 1)
fprintf(outcatfile, "\n ");
charstate = '0' + category[newerwhere[k] + n2];
putc(charstate, outcatfile);
if (n % 10 == 0 && n % 60 != 0)
putc(' ', outcatfile);
}
}
if (interleaved) {
l += 60;
m += 60;
}
} while (interleaved && l <= newersites);
fprintf(outcatfile, "\n");
} /* writecategories */
void writeauxdata(steptr auxdata, FILE *outauxfile)
{
/* write out auxiliary option data (mixtures, ancestors, etc.) to
appropriate file. Samples parralel to data, or just gives one
output entry if justwts is true */
long k, l, m, n, n2;
Char charstate;
/* if we just output weights (justwts), and this is first set
just output the data unsampled */
if(justwts){
if(firstrep){
if (interleaved)
m = 60;
else
m = sites;
l=1;
do {
if(m > sites)
m = sites;
n = 0;
for(k=l-1 ; k < m ; k++){
n++;
if (!interleaved && n > 1 && n % 60 == 1)
fprintf(outauxfile, "\n ");
charstate = auxdata[k];
putc(charstate, outauxfile);
}
if (interleaved) {
l += 60;
m += 60;
}
}while(interleaved && l <= sites);
fprintf(outauxfile, "\n");
}
return;
}
l = 1;
if (interleaved)
m = 60;
else
m = newergroups;
do {
if (m > newergroups)
m = newergroups;
n = 0;
for (k = l - 1; k < m; k++) {
for (n2 = -1; n2 <= (newerhowmany[k] - 2); n2++) {
n++;
if (!interleaved && n > 1 && n % 60 == 1)
fprintf(outauxfile, "\n ");
charstate = auxdata[newerwhere[k] + n2];
putc(charstate, outauxfile);
if (n % 10 == 0 && n % 60 != 0)
putc(' ', outauxfile);
}
}
if (interleaved) {
l += 60;
m += 60;
}
} while (interleaved && l <= newersites);
fprintf(outauxfile, "\n");
} /* writeauxdata */
void writefactors(void)
{
long i, k, l, m, n, writesites;
char symbol;
/*steptr wfactor;*/
long grp;
if(!justwts || firstrep){
if(justwts){
writesites = sites;
/*wfactor = factorr;*/
} else {
writesites = newergroups;
/*wfactor = newerfactor;*/
}
symbol = '+';
if (interleaved)
m = 60;
else
m = writesites;
l=1;
do {
if(m > writesites)
m = writesites;
n = 0;
for(k=l-1 ; k < m ; k++){
grp = charorder[0][k];
for(i = 0; i < newerhowmany[grp]; i++) {
putc(symbol, outfactfile);
n++;
if (!interleaved && n > 1 && n % 60 == 1)
fprintf(outfactfile, "\n ");
if (n % 10 == 0 && n % 60 != 0)
putc(' ', outfactfile);
}
symbol = (symbol == '+') ? '-' : '+';
}
if (interleaved) {
l += 60;
m += 60;
}
}while(interleaved && l <= writesites);
fprintf(outfactfile, "\n");
}
} /* writefactors */
void bootwrite()
{ /* does bootstrapping and writes out data sets */
long i, j, rr, repdiv10;
if (rewrite)
reps = 1;
repdiv10 = reps / 10;
if (repdiv10 < 1)
repdiv10 = 1;
if (progress)
putchar('\n');
firstrep = true;
for (rr = 1; rr <= (reps); rr++) {
bootweights();
for (i = 0; i < spp; i++)
for (j = 0; j < newergroups; j++)
charorder[i][j] = j;
if (ild) {
charpermute(0, newergroups);
for (i = 1; i < spp; i++)
for (j = 0; j < newergroups; j++)
charorder[i][j] = charorder[0][j];
}
if (lockhart)
for (i = 0; i < spp; i++)
charpermute(i, newergroups);
if (!justwts || permute || ild || lockhart)
writedata();
if (justwts && !(permute || ild || lockhart))
writeweights();
if (categories)
writecategories();
if (factors)
writefactors();
if (mixture)
writeauxdata(mixdata, outmixfile);
if (ancvar)
writeauxdata(ancdata, outancfile);
if (progress && !rewrite && ((reps < 10) || rr % repdiv10 == 0)) {
printf("completed replicate number %4ld\n", rr);
#ifdef WIN32
phyFillScreenColor();
#endif
firstrep = false;
}
}
if (progress) {
if (justwts)
printf("\nOutput weights written to file \"%s\"\n\n", outweightfilename);
else
printf("\nOutput written to file \"%s\"\n\n", outfilename);
}
} /* bootwrite */
int main(int argc, Char *argv[])
{ /* Read in sequences or frequencies and bootstrap or jackknife them */
#ifdef MAC
argc = 1; /* macsetup("SeqBoot",""); */
argv[0] = "SeqBoot";
#endif
init(argc,argv);
emboss_getoptions("fseqboot", argc, argv);
ibmpc = IBMCRT;
ansi = ANSICRT;
doinput(argc, argv);
bootwrite();
freenewer();
freenew();
freerest();
if (nodep)
matrix_char_delete(nodep, spp);
if (nodef)
matrix_double_delete(nodef, spp);
FClose(infile);
if (factors) {
FClose(factfile);
FClose(outfactfile);
}
if (weights)
FClose(weightfile);
if (categories) {
FClose(catfile);
FClose(outcatfile);
}
if(mixture)
FClose(outmixfile);
if(ancvar)
FClose(outancfile);
if (justwts && !permute) {
FClose(outweightfile);
}
else
FClose(outfile);
#ifdef MAC
fixmacfile(outfilename);
if (justwts && !permute)
fixmacfile(outweightfilename);
if (categories)
fixmacfile(outcatfilename);
if (mixture)
fixmacfile(outmixfilename);
#endif
if(progress)
printf("Done.\n\n");
#ifdef WIN32
phyRestoreConsoleAttributes();
#endif
embExit();
return 0;
}
PHYLIPNEW-3.69.650/src/promlk.c 0000664 0001750 0001750 00000253643 11616234204 012541 0000000 0000000 /* PHYLIP version 3.6. (c) Copyright 1986-2007 by the University of
* Washington and by Joseph Felsenstein. Written by Joseph
* Felsenstein. Permission is granted to copy and use this program
* provided no fee is charged for it and provided that this copyright
* notice is not removed. */
#include "phylip.h"
#include "seq.h"
#include "mlclock.h"
#include "printree.h"
#define epsilon 0.0001 /* used in makenewv, getthree, update */
#define over 60
typedef long vall[maxcategs];
typedef double contribarr[maxcategs];
AjPSeqset* seqsets = NULL;
AjPPhyloProp phyloratecat = NULL;
AjPPhyloProp phyloweights = NULL;
AjPPhyloTree* phylotrees;
ajint numseqs;
ajint numwts;
#ifndef OLDC
/* function prototypes */
void init_protmats(void);
//void getoptions(void);
void emboss_getoptions(char *pgm, int argc, char *argv[]);
void initmemrates(void);
void makeprotfreqs(void);
void allocrest(void);
void doinit(void);
void inputoptions(void);
void input_protdata(AjPSeqset, long);
void makeweights(void);
void prot_makevalues(long, pointarray, long, long, sequence, steptr);
void getinput(void);
void prot_inittable(void);
void alloc_pmatrix(long);
void make_pmatrix(double **, double **, double **, long, double, double,
double *, double **);
boolean prot_nuview(node *);
void getthree(node *p, double thigh, double tlow);
void update(node *);
void smooth(node *);
void promlk_add(node *, node *, node *, boolean);
void promlk_re_move(node **, node **, boolean);
double prot_evaluate(node *);
void tryadd(node *, node **, node **);
void addpreorder(node *, node *, node *, boolean);
void restoradd(node *, node *, node *, double);
void tryrearr(node *, boolean *);
void repreorder(node *, boolean *);
void rearrange(node **);
void nodeinit(node *);
void initrav(node *);
void travinit(node *);
void travsp(node *);
void treevaluate(void);
void prot_reconstr(node *, long);
void rectrav(node *, long, long);
void summarize(void);
void promlk_treeout(node *);
void initpromlnode(node **, node **, node *, long, long, long *, long *,
initops, pointarray, pointarray, Char *, Char *, char**);
void tymetrav(node *, double *);
void free_all_protx(long, pointarray);
void maketree(void);
void clean_up(void);
void reallocsites(void);
void prot_freetable(void);
void free_pmatrix(long sib);
void invalidate_traverse(node *p);
void invalidate_tyme(node *p);
/* function prototypes */
#endif /* OLDC */
extern sequence y;
double **tbl;
const char* outfilename;
const char* outtreename;
AjPFile embossoutfile;
AjPFile embossouttree;
Char infilename[FNMLNGTH], intreename[FNMLNGTH],
catfilename[FNMLNGTH], weightfilename[FNMLNGTH];
double *rrate;
long sites, weightsum, categs, datasets, ith, njumble, jumb, numtrees, shimotrees;
/* sites = number of sites in actual sequences
numtrees = number of user-defined trees */
long inseed, inseed0, mx, mx0, mx1;
boolean global, jumble, trout, usertree, weights, rctgry, ctgry,
auto_, progress, mulsets, firstset, hypstate, smoothit,
polishing, justwts, gama, invar, usejtt, usepmb, usepam;
boolean lengthsopt = false; /* Use lengths in user tree option */
boolean lngths = false; /* Actually use lengths (depends on
each input tree) */
tree curtree, bestree, bestree2;
node *qwhere, *grbg;
double sumrates, cv, alpha, lambda, lambda1, invarfrac;
long *enterorder;
steptr aliasweight;
double *rate;
longer seed;
double *probcat;
contribarr *contribution;
char aachar[26]="ARNDCQEGHILKMFPSTWYVBZX?*-";
char *progname;
long rcategs, nonodes2;
boolean mnv_success = false;
/* Local variables for maketree, propagated globally for C version: */
long k, maxwhich, col;
double like, bestyet, tdelta, lnlike, slope, curv, maxlogl;
boolean lastsp, smoothed, succeeded;
double *l0gl;
double x[3], lnl[3];
double expon1i[maxcategs], expon1v[maxcategs],
expon2i[maxcategs], expon2v[maxcategs];
node *there;
double **l0gf;
Char ch, ch2;
vall *mp;
/* Variables introduced to allow for protein probability calculations */
long max_num_sibs; /* maximum number of siblings used in a */
/* nuview calculation. determines size */
/* final size of pmatrices */
double *eigmat; /* eig matrix variable */
double **probmat; /* prob matrix variable */
double ****dpmatrix; /* derivative of pmatrix */
double ****ddpmatrix; /* derivative of xpmatrix */
double *****pmatrices; /* matrix of probabilities of protien */
/* conversion. The 5 subscripts refer */
/* to sibs, rcategs, categs, final and */
/* initial states, respectively. */
double freqaa[20]; /* amino acid frequencies */
/* this jtt matrix decomposition due to Elisabeth Tillier */
static double jtteigmat[] =
{+0.00000000000000,-1.81721720738768,-1.87965834528616,-1.61403121885431,
-1.53896608443751,-1.40486966367848,-1.30995061286931,-1.24668414819041,
-1.17179756521289,-0.31033320987464,-0.34602837857034,-1.06031718484613,
-0.99900602987105,-0.45576774888948,-0.86014403434677,-0.54569432735296,
-0.76866956571861,-0.60593589295327,-0.65119724379348,-0.70249806480753};
static double jttprobmat[20][20] =
{{+0.07686196156903,+0.05105697447152,+0.04254597872702,+0.05126897436552,
+0.02027898986051,+0.04106097946952,+0.06181996909002,+0.07471396264303,
+0.02298298850851,+0.05256897371552,+0.09111095444453,+0.05949797025102,
+0.02341398829301,+0.04052997973502,+0.05053197473402,+0.06822496588753,
+0.05851797074102,+0.01433599283201,+0.03230298384851,+0.06637396681302},
{-0.04445795120462,-0.01557336502860,-0.09314817363516,+0.04411372100382,
-0.00511178725134,+0.00188472427522,-0.02176250428454,-0.01330231089224,
+0.01004072641973,+0.02707838224285,-0.00785039050721,+0.02238829876349,
+0.00257470703483,-0.00510311699563,-0.01727154263346,+0.20074235330882,
-0.07236268502973,-0.00012690116016,-0.00215974664431,-0.01059243778174},
{+0.09480046389131,+0.00082658405814,+0.01530023104155,-0.00639909042723,
+0.00160605602061,+0.00035896642912,+0.00199161318384,-0.00220482855717,
-0.00112601328033,+0.14840201765438,-0.00344295714983,-0.00123976286718,
-0.00439399942758,+0.00032478785709,-0.00104270266394,-0.02596605592109,
-0.05645800566901,+0.00022319903170,-0.00022792271829,-0.16133258048606},
{-0.06924141195400,-0.01816245289173,-0.08104005811201,+0.08985697111009,
+0.00279659017898,+0.01083740322821,-0.06449599336038,+0.01794514261221,
+0.01036809141699,+0.04283504450449,+0.00634472273784,+0.02339134834111,
-0.01748667848380,+0.00161859106290,+0.00622486432503,-0.05854130195643,
+0.15083728660504,+0.00030733757661,-0.00143739522173,-0.05295810171941},
{-0.14637948915627,+0.02029296323583,+0.02615316895036,-0.10311538564943,
-0.00183412744544,-0.02589124656591,+0.11073673851935,+0.00848581728407,
+0.00106057791901,+0.05530240732939,-0.00031533506946,-0.03124002869407,
-0.01533984125301,-0.00288717337278,+0.00272787410643,+0.06300929916280,
+0.07920438311152,-0.00041335282410,-0.00011648873397,-0.03944076085434},
{-0.05558229086909,+0.08935293782491,+0.04869509588770,+0.04856877988810,
-0.00253836047720,+0.07651693957635,-0.06342453535092,-0.00777376246014,
-0.08570270266807,+0.01943016473512,-0.00599516526932,-0.09157595008575,
-0.00397735155663,-0.00440093863690,-0.00232998056918,+0.02979967701162,
-0.00477299485901,-0.00144011795333,+0.01795114942404,-0.00080059359232},
{+0.05807741644682,+0.14654292420341,-0.06724975334073,+0.02159062346633,
-0.00339085518294,-0.06829036785575,+0.03520631903157,-0.02766062718318,
+0.03485632707432,-0.02436836692465,-0.00397566003573,-0.10095488644404,
+0.02456887654357,+0.00381764117077,-0.00906261340247,-0.01043058066362,
+0.01651199513994,-0.00210417220821,-0.00872508520963,-0.01495915462580},
{+0.02564617106907,+0.02960554611436,-0.00052356748770,+0.00989267817318,
-0.00044034172141,-0.02279910634723,-0.00363768356471,-0.01086345665971,
+0.01229721799572,+0.02633650142592,+0.06282966783922,-0.00734486499924,
-0.13863936313277,-0.00993891943390,-0.00655309682350,-0.00245191788287,
-0.02431633805559,-0.00068554031525,-0.00121383858869,+0.06280025239509},
{+0.11362428251792,-0.02080375718488,-0.08802750967213,-0.06531316372189,
-0.00166626058292,+0.06846081717224,+0.07007301248407,-0.01713112936632,
-0.05900588794853,-0.04497159138485,+0.04222484636983,+0.00129043178508,
-0.01550337251561,-0.01553102163852,-0.04363429852047,+0.01600063777880,
+0.05787328925647,-0.00008265841118,+0.02870014572813,-0.02657681214523},
{+0.01840541226842,+0.00610159018805,+0.01368080422265,+0.02383751807012,
-0.00923516894192,+0.01209943150832,+0.02906782189141,+0.01992384905334,
+0.00197323568330,+0.00017531415423,-0.01796698381949,+0.01887083962858,
-0.00063335886734,-0.02365277334702,+0.01209445088200,+0.01308086447947,
+0.01286727242301,-0.11420358975688,-0.01886991700613,+0.00238338728588},
{-0.01100105031759,-0.04250695864938,-0.02554356700969,-0.05473632078607,
+0.00725906469946,-0.03003724918191,-0.07051526125013,-0.06939439879112,
-0.00285883056088,+0.05334304124753,+0.12839241846919,-0.05883473754222,
+0.02424304967487,+0.09134510778469,-0.00226003347193,-0.01280041778462,
-0.00207988305627,-0.02957493909199,+0.05290385686789,+0.05465710875015},
{-0.01421274522011,+0.02074863337778,-0.01006411985628,+0.03319995456446,
-0.00005371699269,-0.12266046460835,+0.02419847062899,-0.00441168706583,
-0.08299118738167,-0.00323230913482,+0.02954035119881,+0.09212856795583,
+0.00718635627257,-0.02706936115539,+0.04473173279913,-0.01274357634785,
-0.01395862740618,-0.00071538848681,+0.04767640012830,-0.00729728326990},
{-0.03797680968123,+0.01280286509478,-0.08614616553187,-0.01781049963160,
+0.00674319990083,+0.04208667754694,+0.05991325707583,+0.03581015660092,
-0.01529816709967,+0.06885987924922,-0.11719120476535,-0.00014333663810,
+0.00074336784254,+0.02893416406249,+0.07466151360134,-0.08182016471377,
-0.06581536577662,-0.00018195976501,+0.00167443595008,+0.09015415667825},
{+0.03577726799591,-0.02139253448219,-0.01137813538175,-0.01954939202830,
-0.04028242801611,-0.01777500032351,-0.02106862264440,+0.00465199658293,
-0.02824805812709,+0.06618860061778,+0.08437791757537,-0.02533125946051,
+0.02806344654855,-0.06970805797879,+0.02328376968627,+0.00692992333282,
+0.02751392122018,+0.01148722812804,-0.11130404325078,+0.07776346000559},
{-0.06014297925310,-0.00711674355952,-0.02424493472566,+0.00032464353156,
+0.00321221847573,+0.03257969053884,+0.01072805771161,+0.06892027923996,
+0.03326534127710,-0.01558838623875,+0.13794237677194,-0.04292623056646,
+0.01375763233229,-0.11125153774789,+0.03510076081639,-0.04531670712549,
-0.06170413486351,-0.00182023682123,+0.05979891871679,-0.02551802851059},
{-0.03515069991501,+0.02310847227710,+0.00474493548551,+0.02787717003457,
-0.12038329679812,+0.03178473522077,+0.04445111601130,-0.05334957493090,
+0.01290386678474,-0.00376064171612,+0.03996642737967,+0.04777677295520,
+0.00233689200639,+0.03917715404594,-0.01755598277531,-0.03389088626433,
-0.02180780263389,+0.00473402043911,+0.01964539477020,-0.01260807237680},
{-0.04120428254254,+0.00062717164978,-0.01688703578637,+0.01685776910152,
+0.02102702093943,+0.01295781834163,+0.03541815979495,+0.03968150445315,
-0.02073122710938,-0.06932247350110,+0.11696314241296,-0.00322523765776,
-0.01280515661402,+0.08717664266126,+0.06297225078802,-0.01290501780488,
-0.04693925076877,-0.00177653675449,-0.08407812137852,-0.08380714022487},
{+0.03138655228534,-0.09052573757196,+0.00874202219428,+0.06060593729292,
-0.03426076652151,-0.04832468257386,+0.04735628794421,+0.14504653737383,
-0.01709111334001,-0.00278794215381,-0.03513813820550,-0.11690294831883,
-0.00836264902624,+0.03270980973180,-0.02587764129811,+0.01638786059073,
+0.00485499822497,+0.00305477087025,+0.02295754527195,+0.00616929722958},
{-0.04898722042023,-0.01460879656586,+0.00508708857036,+0.07730497806331,
+0.04252420017435,+0.00484232580349,+0.09861807969412,-0.05169447907187,
-0.00917820907880,+0.03679081047330,+0.04998537112655,+0.00769330211980,
+0.01805447683564,-0.00498723245027,-0.14148416183376,-0.05170281760262,
-0.03230723310784,-0.00032890672639,-0.02363523071957,+0.03801365471627},
{-0.02047562162108,+0.06933781779590,-0.02101117884731,-0.06841945874842,
-0.00860967572716,-0.00886650271590,-0.07185241332269,+0.16703684361030,
-0.00635847581692,+0.00811478913823,+0.01847205842216,+0.06700967948643,
+0.00596607376199,+0.02318239240593,-0.10552958537847,-0.01980199747773,
-0.02003785382406,-0.00593392430159,-0.00965391033612,+0.00743094349652}};
/* dcmut version of PAM model from http://www.ebi.ac.uk/goldman-srv/dayhoff/ */
static double pameigmat[] =
{0,-1.93321786301018,-2.20904642493621,-1.74835983874903,
-1.64854548332072,-1.54505559488222,-1.33859384676989,-1.29786201193594,
-0.235548517495575,-0.266951066089808,-0.28965813670665,-1.10505826965282,
-1.04323310568532,-0.430423720979904,-0.541719761016713,-0.879636093986914,
-0.711249353378695,-0.725050487280602,-0.776855937389452,-0.808735559461343};
static double pamprobmat[20][20] ={
{0.08712695644, 0.04090397955, 0.04043197978, 0.04687197656,
0.03347398326, 0.03825498087, 0.04952997524, 0.08861195569,
0.03361898319, 0.03688598156, 0.08535695732, 0.08048095976,
0.01475299262, 0.03977198011, 0.05067997466, 0.06957696521,
0.05854197073, 0.01049399475, 0.02991598504, 0.06471796764},
{0.07991048383, 0.006888314018, 0.03857806206, 0.07947073194,
0.004895492884, 0.03815829405, -0.1087562465, 0.008691167141,
-0.0140554828, 0.001306404001, -0.001888411299, -0.006921303342,
0.0007655604228, 0.001583298443, 0.006879590446, -0.171806883,
0.04890917949, 0.0006700432804, 0.0002276237277, -0.01350591875},
{-0.01641514483, -0.007233933239, -0.1377830621, 0.1163201333,
-0.002305138017, 0.01557250366, -0.07455879489, -0.003225343503,
0.0140630487, 0.005112274204, 0.001405731862, 0.01975833782,
-0.001348402973, -0.001085733262, -0.003880514478, 0.0851493313,
-0.01163526615, -0.0001197903399, 0.002056153393, 0.0001536095643},
{0.009669278686, -0.006905863869, 0.101083544, 0.01179903104,
-0.003780967591, 0.05845105878, -0.09138357299, -0.02850503638,
-0.03233951408, 0.008708065876, -0.004700705411, -0.02053221579,
0.001165851398, -0.001366585849, -0.01317695074, 0.1199985703,
-0.1146346193, -0.0005953021314, -0.0004297615194, 0.007475695618},
{0.1722243502, -0.003737582995, -0.02964873222, -0.02050116381,
-0.0004530478465, -0.02460043205, 0.02280768412, -0.02127364909,
0.01570095258, 0.1027744285, -0.005330539586, 0.0179697651,
-0.002904077286, -0.007068126663, -0.0142869583, -0.01444241844,
-0.08218861544, 0.0002069181629, 0.001099671379, -0.1063484263},
{-0.1553433627, -0.001169168032, 0.02134785337, 0.0007602305436,
0.0001395330122, 0.03194992019, -0.01290252206, 0.03281720789,
-0.01311103735, 0.1177254769, -0.008008783885, -0.02375317548,
-0.002817809762, -0.008196682776, 0.01731267617, 0.01853526375,
0.08249908546, -2.788771776e-05, 0.001266182191, -0.09902299976},
{-0.03671080341, 0.0274168035, 0.04625877597, 0.07520706414,
-0.0001833803619, -0.1207833161, -0.006415807779, -0.005465629648,
0.02778273972, 0.007589688485, -0.02945266034, -0.03797542064,
0.07044042052, -0.002018573865, 0.01845277071, 0.006901513991,
-0.02430934639, -0.0005919635873, -0.001266962331, -0.01487591261},
{-0.03060317816, 0.01182361623, 0.04200270053, 0.05406235279,
-0.0003920498815, -0.09159709348, -0.009602690652, -0.00382944418,
0.01761361993, 0.01605684317, 0.05198878008, 0.02198696949,
-0.09308930025, -0.00102622863, 0.01477637127, 0.0009314065393,
-0.01860959472, -0.0005964703968, -0.002694284083, 0.02079767439},
{0.0195976494, -0.005104484936, 0.007406728707, 0.01236244954,
0.0201446796, 0.007039564785, 0.01276942134, 0.02641595685,
0.002764624354, 0.001273314658, -0.01335316035, 0.01105658671,
2.148773499e-05, -0.02692205639, 0.0118684991, 0.01212624708,
0.01127770094, -0.09842754796, -0.01942336432, 0.007105703151},
{-0.01819461888, -0.01509348507, -0.01297636935, -0.01996453439,
0.1715705905, -0.01601550692, -0.02122706144, -0.02854628494,
-0.009351082371, -0.001527995472, -0.010198224, -0.03609537551,
-0.003153182095, 0.02395980501, -0.01378664626, -0.005992611421,
-0.01176810875, 0.003132361603, 0.03018439539, -0.004956065656},
{-0.02733614784, -0.02258066705, -0.0153112506, -0.02475728664,
-0.04480525045, -0.01526640341, -0.02438517425, -0.04836914601,
-0.00635964824, 0.02263169831, 0.09794101931, -0.04004304158,
0.008464393478, 0.1185443142, -0.02239294163, -0.0281550321,
-0.01453581604, -0.0246742804, 0.0879619849, 0.02342867605},
{0.06483718238, 0.1260012082, -0.006496013283, 0.009914915531,
-0.004181603532, 0.0003493226286, 0.01408035752, -0.04881663016,
-0.03431167356, -0.01768005602, 0.02362447761, -0.1482364784,
-0.01289035619, -0.001778893279, -0.05240099752, 0.05536174567,
0.06782165352, -0.003548568717, 0.001125301173, -0.03277489363},
{0.06520296909, -0.0754802543, 0.03139281903, -0.03266449554,
-0.004485188002, -0.03389072036, -0.06163274338, -0.06484769882,
0.05722658289, -0.02824079619, 0.01544837349, 0.03909752708,
0.002029218884, 0.003151939572, -0.05471208363, 0.07962008342,
0.125916047, 0.0008696184937, -0.01086027514, -0.05314092355},
{0.004543119081, 0.01935177735, 0.01905511007, 0.02682993409,
-0.01199617967, 0.01426278655, 0.02472521255, 0.03864795501,
0.02166224804, -0.04754243479, -0.1921545477, 0.03621321546,
-0.02120627881, 0.04928097895, 0.009396088815, 0.01748042052,
-6.173742851e-05, -0.003168033098, 0.07723565812, -0.08255529309},
{0.06710378668, -0.09441410284, -0.004801776989, 0.008830272165,
-0.01021645042, -0.02764365608, 0.004250361851, 0.1648777542,
-0.037446109, 0.004541057635, -0.0296980702, -0.1532325189,
-0.008940580901, 0.006998050812, 0.02338809379, 0.03175059182,
0.02033965512, 0.006388075608, 0.001762762044, 0.02616280361},
{0.01915943021, -0.05432967274, 0.01249342683, 0.06836622457,
0.002054462161, -0.01233535859, 0.07087282652, -0.08948637051,
-0.1245896013, -0.02204522882, 0.03791481736, 0.06557467874,
0.005529294156, -0.006296644235, 0.02144530752, 0.01664230081,
0.02647078439, 0.001737725271, 0.01414149877, -0.05331990116},
{0.0266659303, 0.0564142853, -0.0263767738, -0.08029726006,
-0.006059357163, -0.06317558457, -0.0911894019, 0.05401487057,
-0.08178072458, 0.01580699778, -0.05370550396, 0.09798653264,
0.003934944022, 0.01977291947, 0.0441198541, 0.02788220393,
0.03201877081, -0.00206161759, -0.005101423308, 0.03113033802},
{0.02980360751, -0.009513246268, -0.009543527165, -0.02190644172,
-0.006146440672, 0.01207009085, -0.0126989156, -0.1378266418,
0.0275235217, 0.00551720592, -0.03104791544, -0.07111701247,
-0.006081754489, -0.01337494521, 0.1783961085, 0.01453225059,
0.01938736048, 0.0004488631071, 0.0110844398, 0.02049339243},
{-0.01433508581, 0.01258858175, -0.004294252236, -0.007146532854,
0.009541628809, 0.008040155729, -0.006857781832, 0.05584120066,
0.007749418365, -0.05867835844, 0.08008131283, -0.004877854222,
-0.0007128540743, 0.09489058424, 0.06421121962, 0.00271493526,
-0.03229944773, -0.001732026038, -0.08053448316, -0.1241903609},
{-0.009854113227, 0.01294129929, -0.00593064392, -0.03016833115,
-0.002018439732, -0.00792418722, -0.03372768732, 0.07828561288,
0.007722254639, -0.05067377561, 0.1191848621, 0.005059475202,
0.004762387166, -0.1029870175, 0.03537190114, 0.001089956203,
-0.02139157573, -0.001015245062, 0.08400521847, -0.08273195059}};
/* this pmb matrix decomposition due to Elisabeth Tillier */
static double pmbeigmat[20] =
{0.0000001586972220,-1.8416770496147100, -1.6025046986139100,-1.5801012515121300,
-1.4987794099715900,-1.3520794233801900,-1.3003469390479700,-1.2439503327631300,
-1.1962574080244200,-1.1383730501367500,-1.1153278910708000,-0.4934843510654760,
-0.5419014550215590,-0.9657997830826700,-0.6276075673757390,-0.6675927795018510,
-0.6932641383465870,-0.8897872681859630,-0.8382698977371710,-0.8074694642446040};
static double pmbprobmat[20][20] =
{{0.0771762457248147,0.0531913844998640,0.0393445076407294,0.0466756566755510,
0.0286348361997465,0.0312327748383639,0.0505410248721427,0.0767106611472993,
0.0258916271688597,0.0673140562194124,0.0965705469252199,0.0515979465932174,
0.0250628079438675,0.0503492018628350,0.0399908189418273,0.0641898881894471,
0.0517539616710987,0.0143507440546115,0.0357994592438322,0.0736218495862984},
{0.0368263046116572,-0.0006728917107827,0.0008590805287740,-0.0002764255356960,
0.0020152937187455,0.0055743720652960,0.0003213317669367,0.0000449190281568,
-0.0004226254397134,0.1805040629634510,-0.0272246813586204,0.0005904606533477,
-0.0183743200073889,-0.0009194625608688,0.0008173657533167,-0.0262629806302238,
0.0265738757209787,0.0002176606241904,0.0021315644838566,-0.1823229927207580},
{-0.0194800075560895,0.0012068088610652,-0.0008803318319596,-0.0016044273960017,
-0.0002938633803197,-0.0535796754602196,0.0155163896648621,-0.0015006360762140,
0.0021601372013703,0.0268513218744797,-0.1085292493742730,0.0149753083138452,
0.1346457366717310,-0.0009371698759829,0.0013501708044116,0.0346352293103622,
-0.0276963770242276,0.0003643142783940,0.0002074817333067,-0.0174108903914110},
{0.0557839400850153,0.0023271577185437,0.0183481103396687,0.0023339480096311,
0.0002013267015151,-0.0227406863569852,0.0098644845475047,0.0064721276774396,
0.0001389408104210,-0.0473713878768274,-0.0086984445005797,0.0026913674934634,
0.0283724052562196,0.0001063665179457,0.0027442574779383,-0.1875312134708470,
0.1279864877057640,0.0005103347834563,0.0003155113168637,0.0081451082759554},
{0.0037510125027265,0.0107095920636885,0.0147305410328404,-0.0112351252180332,
-0.0001500408626446,-0.1523450933729730,0.0611532413339872,-0.0005496748939503,
0.0048714378736644,-0.0003826320053999,0.0552010244407311,0.0482555671001955,
-0.0461664995115847,-0.0021165008617978,-0.0004574454232187,0.0233755883688949,
-0.0035484915422384,0.0009090698422851,0.0013840637687758,-0.0073895139302231},
{-0.0111512564930024,0.1025460064723080,0.0396772456883791,-0.0298408501361294,
-0.0001656742634733,-0.0079876311843289,0.0712644184507945,-0.0010780604625230,
-0.0035880882043592,0.0021070399334252,0.0016716329894279,-0.1810123023850110,
0.0015141703608724,-0.0032700852781804,0.0035503782441679,0.0118634302028026,
0.0044561606458028,-0.0001576678495964,0.0023470722225751,-0.0027457045397157},
{0.1474525743949170,-0.0054432538500293,0.0853848892349828,-0.0137787746207348,
-0.0008274830358513,0.0042248844582553,0.0019556229305563,-0.0164191435175148,
-0.0024501858854849,0.0120908948084233,-0.0381456105972653,0.0101271614855119,
-0.0061945941321859,0.0178841099895867,-0.0014577779202600,-0.0752120602555032,
-0.1426985695849920,0.0002862275078983,-0.0081191734261838,0.0313401149422531},
{0.0542034611735289,-0.0078763926211829,0.0060433542506096,0.0033396210615510,
0.0013965072374079,0.0067798903832256,-0.0135291136622509,-0.0089982442731848,
-0.0056744537593887,-0.0766524225176246,0.1881210263933930,-0.0065875518675173,
0.0416627569300375,-0.0953804133524747,-0.0012559228448735,0.0101622644292547,
-0.0304742453119050,0.0011702318499737,0.0454733434783982,-0.1119239362388150},
{0.1069409037912470,0.0805064400880297,-0.1127352030714600,0.1001181253523260,
-0.0021480427488769,-0.0332884841459003,-0.0679837575848452,-0.0043812841356657,
0.0153418716846395,-0.0079441315103188,-0.0121766182046363,-0.0381127991037620,
-0.0036338726532673,0.0195324059593791,-0.0020165963699984,-0.0061222685010268,
-0.0253761448771437,-0.0005246410999057,-0.0112205170502433,0.0052248485517237},
{-0.0325247648326262,0.0238753651653669,0.0203684886605797,0.0295666232678825,
-0.0003946714764213,-0.0157242718469554,-0.0511737848084862,0.0084725632040180,
-0.0167068828528921,0.0686962159427527,-0.0659702890616198,-0.0014289912494271,
-0.0167000964093416,-0.1276689083678200,0.0036575057830967,-0.0205958145531018,
0.0000368919612829,0.0014413626622426,0.1064360941926030,0.0863372661517408},
{-0.0463777468104402,0.0394712148670596,0.1118686750747160,0.0440711686389031,
-0.0026076286506751,-0.0268454015202516,-0.1464943067133240,-0.0137514051835380,
-0.0094395514284145,-0.0144124844774228,0.0249103379323744,-0.0071832157138676,
0.0035592787728526,0.0415627419826693,0.0027040097365669,0.0337523666612066,
0.0316121324137152,-0.0011350177559026,-0.0349998884574440,-0.0302651879823361},
{0.0142360925194728,0.0413145623127025,0.0324976427846929,0.0580930922002398,
-0.0586974207121084,0.0202001168873069,0.0492204086749069,0.1126593173463060,
0.0116620013776662,-0.0780333711712066,-0.1109786767320410,0.0407775100936731,
-0.0205013161312652,-0.0653458585025237,0.0347351829703865,0.0304448983224773,
0.0068813748197884,-0.0189002309261882,-0.0334507528405279,-0.0668143558699485},
{-0.0131548829657936,0.0044244322828034,-0.0050639951827271,-0.0038668197633889,
-0.1536822386530220,0.0026336969165336,0.0021585651200470,-0.0459233839062969,
0.0046854727140565,0.0393815434593599,0.0619554007991097,0.0027456299925622,
0.0117574347936383,0.0373018612990383,0.0024818527553328,-0.0133956606027299,
-0.0020457128424105,0.0154178819990401,0.0246524142683911,0.0275363065682921},
{-0.1542307272455030,0.0364861558267547,-0.0090880407008181,0.0531673937889863,
0.0157585615170580,0.0029986538457297,0.0180194047699875,0.0652152443589317,
0.0266842840376180,0.0388457366405908,0.0856237634510719,0.0126955778952183,
0.0099593861698250,-0.0013941794862563,0.0294065511237513,-0.1151906949298290,
-0.0852991447389655,0.0028699120202636,-0.0332087026659522,0.0006811857297899},
{0.0281300736924501,-0.0584072081898638,-0.0178386569847853,-0.0536470338171487,
-0.0186881656029960,-0.0240008730656106,-0.0541064820498883,0.2217137098936020,
-0.0260500001542033,0.0234505236798375,0.0311127151218573,-0.0494139126682672,
0.0057093465049849,0.0124937286655911,-0.0298322975915689,0.0006520211333102,
-0.0061018680727128,-0.0007081999479528,-0.0060523759094034,0.0215845995364623},
{0.0295321046399105,-0.0088296411830544,-0.0065057049917325,-0.0053478115612781,
-0.0100646496794634,-0.0015473619084872,0.0008539960632865,-0.0376381933046211,
-0.0328135588935604,0.0672161874239480,0.0667626853916552,-0.0026511651464901,
0.0140451514222062,-0.0544836996133137,0.0427485157912094,0.0097455780205802,
0.0177309072915667,-0.0828759701187452,-0.0729504795471370,0.0670731961252313},
{0.0082646581043963,-0.0319918630534466,-0.0188454445200422,-0.0374976353856606,
0.0037131290686848,-0.0132507796987883,-0.0306958830735725,-0.0044119395527308,
-0.0140786756619672,-0.0180512599925078,-0.0208243802903953,-0.0232202769398931,
-0.0063135878270273,0.0110442171178168,0.1824538048228460,-0.0006644614422758,
-0.0069909097436659,0.0255407650654681,0.0099119399501151,-0.0140911517070698},
{0.0261344441524861,-0.0714454044548650,0.0159436926233439,0.0028462736216688,
-0.0044572637889080,-0.0089474834434532,-0.0177570282144517,-0.0153693244094452,
0.1160919467206400,0.0304911481385036,0.0047047513411774,-0.0456535116423972,
0.0004491494948617,-0.0767108879444462,-0.0012688533741441,0.0192445965934123,
0.0202321954782039,0.0281039933233607,-0.0590403018490048,0.0364080426546883},
{0.0115826306265004,0.1340228176509380,-0.0236200652949049,-0.1284484655137340,
-0.0004742338006503,0.0127617346949511,-0.0428560878860394,0.0060030732454125,
0.0089182609926781,0.0085353834972860,0.0048464809638033,0.0709740071429510,
0.0029940462557054,-0.0483434904493132,-0.0071713680727884,-0.0036840391887209,
0.0031454003250096,0.0246243550241551,-0.0449551277644180,0.0111449232769393},
{0.0140356721886765,-0.0196518236826680,0.0030517022326582,0.0582672093364850,
-0.0000973895685457,0.0021704767224292,0.0341806268602705,-0.0152035987563018,
-0.0903198657739177,0.0259623214586925,0.0155832497882743,-0.0040543568451651,
0.0036477631918247,-0.0532892744763217,-0.0142569373662724,0.0104500681408622,
0.0103483945857315,0.0679534422398752,-0.0768068882938636,0.0280289727046158}}
;
void init_protmats(void)
{
long l;
eigmat = (double *) Malloc (20 * sizeof(double));
for (l = 0; l <= 19; l++)
if (usejtt)
eigmat[l] = jtteigmat[l]; /** changed from jtteigmat*100. **/
else {
if (usepmb)
eigmat[l] = pmbeigmat[l];
else
eigmat[l] = pameigmat[l]; /** changed from pameigmat*100. **/
}
probmat = (double **) Malloc (20 * sizeof(double *));
for (l = 0; l <= 19; l++)
{
if (usejtt)
{
probmat[l] = jttprobmat[l];
}
else
{
if (usepmb)
probmat[l] = pmbprobmat[l];
else
probmat[l] = pamprobmat[l];
}
}
} /* init_protmats */
void emboss_getoptions(char *pgm, int argc, char *argv[])
{
long i;
double probsum;
AjPStr model = NULL;
AjPStr gammamethod = NULL;
AjPFloat hmmrates;
AjPFloat hmmprob;
AjPFloat arrayval;
auto_ = false;
ctgry = false;
rctgry = false;
categs = 1;
rcategs = 1;
gama = false;
global = false;
hypstate = false;
invar = false;
jumble = false;
njumble = 1;
lambda = 1.0;
lambda1 = 0.0;
lngths = false;
trout = true;
usepam = false;
usepmb = false;
usejtt = false;
usertree = false;
weights = false;
printdata = false;
progress = true;
treeprint = true;
interleaved = true;
datasets = 1;
mulsets = false;
embInitPV(pgm, argc, argv, "PHYLIPNEW",VERSION);
seqsets = ajAcdGetSeqsetall("sequence");
numseqs = 0;
while (seqsets[numseqs])
numseqs++;
phylotrees = ajAcdGetTree("intreefile");
if (phylotrees)
{
numtrees = 0;
while (phylotrees[numtrees])
numtrees++;
usertree = true;
lngths = ajAcdGetBoolean("lengths");
}
numwts = 0;
phyloweights = ajAcdGetProperties("weights");
if (phyloweights)
{
weights = true;
numwts = ajPhyloPropGetSize(phyloweights);
}
if (numseqs > 1) {
mulsets = true;
datasets = numseqs;
}
else if (numwts > 1) {
mulsets = true;
datasets = numwts;
justwts = true;
}
model = ajAcdGetListSingle("model");
if(ajStrMatchC(model, "j")) usejtt = true;
if(ajStrMatchC(model, "h")) usepmb = true;
if(ajStrMatchC(model, "d")) usepam = true;
categs = ajAcdGetInt("ncategories");
if (categs > 1) {
ctgry = true;
rate = (double *) Malloc(categs * sizeof(double));
arrayval = ajAcdGetArray("rate");
emboss_initcategs(arrayval, categs, rate);
}
else{
rate = (double *) Malloc(categs*sizeof(double));
rate[0] = 1.0;
}
phyloratecat = ajAcdGetProperties("categories");
gammamethod = ajAcdGetListSingle("gammatype");
if(ajStrMatchC(gammamethod, "n")) {
rrate = (double *) Malloc(rcategs*sizeof(double));
probcat = (double *) Malloc(rcategs*sizeof(double));
rrate[0] = 1.0;
probcat[0] = 1.0;
}
else {
rctgry = true;
auto_ = ajAcdGetBoolean("adjsite");
if(auto_) {
lambda = ajAcdGetFloat("lambda");
lambda = 1 / lambda;
lambda1 = 1.0 - lambda;
}
}
if(ajStrMatchC(gammamethod, "g")) {
gama = true;
rcategs = ajAcdGetInt("ngammacat");
cv = ajAcdGetFloat("gammacoefficient");
alpha = 1.0 / (cv*cv);
initmemrates();
initgammacat(rcategs, alpha, rrate, probcat);
}
else if(ajStrMatchC(gammamethod, "i")) {
invar = true;
rcategs = ajAcdGetInt("ninvarcat");
cv = ajAcdGetFloat("invarcoefficient");
alpha = 1.0 / (cv*cv);
invarfrac = ajAcdGetFloat("invarfrac");
initmemrates();
initgammacat(rcategs-1, alpha, rrate, probcat);
for (i=0; i < rcategs-1 ; i++)
probcat[i] = probcat[i]*(1.0-invarfrac);
probcat[rcategs-1] = invarfrac;
rrate[rcategs-1] = 0.0;
}
else if(ajStrMatchC(gammamethod, "h")) {
rcategs = ajAcdGetInt("nhmmcategories");
initmemrates();
hmmrates = ajAcdGetArray("hmmrates");
emboss_initcategs(hmmrates, rcategs,rrate);
hmmprob = ajAcdGetArray("hmmprobabilities");
for (i=0; i < rcategs; i++){
probcat[i] = ajFloatGet(hmmprob, i);
probsum += probcat[i];
}
}
outgrno = ajAcdGetInt("outgrno");
if(outgrno != 0) outgropt = true;
else outgrno = 1;
if(!usertree) {
global = ajAcdGetBoolean("global");
njumble = ajAcdGetInt("njumble");
if(njumble >0) {
inseed = ajAcdGetInt("seed");
jumble = true;
emboss_initseed(inseed, &inseed0, seed);
}
else njumble = 1;
}
if((mulsets) && (!jumble)) {
jumble = true;
inseed = ajAcdGetInt("seed");
emboss_initseed(inseed, &inseed0, seed);
}
printdata = ajAcdGetBoolean("printdata");
progress = ajAcdGetBoolean("progress");
treeprint = ajAcdGetBoolean("treeprint");
trout = ajAcdGetToggle("trout");
hypstate = ajAcdGetBoolean("hypstate");
embossoutfile = ajAcdGetOutfile("outfile");
emboss_openfile(embossoutfile, &outfile, &outfilename);
if(trout) {
embossouttree = ajAcdGetOutfile("outtreefile");
emboss_openfile(embossouttree, &outtree, &outtreename);
}
fprintf(outfile, "\nAmino acid sequence\n");
fprintf(outfile, " Maximum Likelihood method with molecular ");
fprintf(outfile, "clock, version %s\n\n", VERSION);
init_protmats();
} /* emboss_getoptions */
void initmemrates(void)
{
probcat = (double *) Malloc(rcategs * sizeof(double));
rrate = (double *) Malloc(rcategs * sizeof(double));
}
void makeprotfreqs(void)
{
/* calculate amino acid frequencies based on eigmat */
long i, mineig;
mineig = 0;
for (i = 0; i <= 19; i++)
if (fabs(eigmat[i]) < fabs(eigmat[mineig]))
mineig = i;
memcpy(freqaa, probmat[mineig], 20 * sizeof(double));
for (i = 0; i <= 19; i++)
freqaa[i] = fabs(freqaa[i]);
} /* makeprotfreqs */
void reallocsites(void)
{
long i;
for (i = 0; i < spp; i++)
y[i] = (char *)Malloc(sites * sizeof(char));
enterorder = (long *)Malloc(spp*sizeof(long));
weight = (long *)Malloc(sites*sizeof(long));
category = (long *)Malloc(sites*sizeof(long));
alias = (long *)Malloc(sites*sizeof(long));
aliasweight = (long *)Malloc(sites*sizeof(long));
ally = (long *)Malloc(sites*sizeof(long));
location = (long *)Malloc(sites*sizeof(long));
for (i = 0; i < sites; i++)
category[i] = 1;
for (i = 0; i < sites; i++)
weight[i] = 1;
makeweights();
} /* reallocsites */
void allocrest(void)
{
long i;
y = (Char **)Malloc(spp*sizeof(Char *));
nayme = (naym *)Malloc(spp*sizeof(naym));
for (i = 0; i < spp; i++)
y[i] = (char *)Malloc((sites+1) * sizeof(char));
enterorder = (long *)Malloc(spp*sizeof(long));
weight = (long *)Malloc(sites*sizeof(long));
category = (long *)Malloc(sites*sizeof(long));
alias = (long *)Malloc(sites*sizeof(long));
aliasweight = (long *)Malloc(sites*sizeof(long));
ally = (long *)Malloc(sites*sizeof(long));
location = (long *)Malloc(sites*sizeof(long));
} /* allocrest */
void doinit()
{
/* initializes variables */
inputnumbersseq(seqsets[0], &spp, &sites, &nonodes, 1);
makeprotfreqs();
if (printdata)
fprintf(outfile, "%2ld species, %3ld sites\n", spp, sites);
alloctree(&curtree.nodep, nonodes, usertree);
allocrest();
if (usertree)
return;
alloctree(&bestree.nodep, nonodes, 0);
if (njumble <= 1)
return;
alloctree(&bestree2.nodep, nonodes, 0);
} /* doinit */
void inputoptions()
{
long i;
if (!firstset) {
samenumspseq(seqsets[ith-1], &sites, ith);
reallocsites();
}
if (firstset) {
for (i = 0; i < sites; i++)
category[i] = 1;
for (i = 0; i < sites; i++)
weight[i] = 1;
}
if (justwts || weights)
inputweightsstr(phyloweights->Str[ith-1], sites, weight, &weights);
weightsum = 0;
for (i = 0; i < sites; i++)
weightsum += weight[i];
if ((ctgry && categs > 1) && (firstset || !justwts)) {
inputcategsstr(phyloratecat->Str[0], 0, sites, category, categs, "ProMLK");
if (printdata)
printcategs(outfile, sites, category, "Site categories");
}
if (weights && printdata)
printweights(outfile, 0, sites, weight, "Sites");
fprintf(outfile, "%s model of amino acid change\n\n",
(usejtt ? "Jones-Taylor-Thornton" :
usepmb ? "Henikoff/Tillier PMB" : "Dayhoff PAM"));
} /* inputoptions */
void input_protdata(AjPSeqset seqset, long chars)
{
/* input the names and sequences for each species */
/* used by proml */
long i, j, k, l;
Char charstate;
if (printdata)
headings(chars, "Sequences", "---------");
for(i=0;i chars)
l = chars;
for (k = (i - 1) * 60 + 1; k <= l; k++) {
if (j > 1 && y[j - 1][k - 1] == y[0][k - 1])
charstate = '.';
else
charstate = y[j - 1][k - 1];
putc(charstate, outfile);
if (k % 10 == 0 && k % 60 != 0)
putc(' ', outfile);
}
putc('\n', outfile);
}
putc('\n', outfile);
}
putc('\n', outfile);
} /* input_protdata */
void makeweights()
{
/* make up weights vector to avoid duplicate computations */
long i;
for (i = 1; i <= sites; i++) {
alias[i - 1] = i;
ally[i - 1] = 0;
aliasweight[i - 1] = weight[i - 1];
location[i - 1] = 0;
}
sitesort2(sites, aliasweight);
sitecombine2(sites, aliasweight);
sitescrunch2(sites, 1, 2, aliasweight);
for (i = 1; i <= sites; i++) {
if (aliasweight[i - 1] > 0)
endsite = i;
}
for (i = 1; i <= endsite; i++) {
ally[alias[i - 1] - 1] = alias[i - 1];
location[alias[i - 1] - 1] = i;
}
mp = (vall *) Malloc(sites*sizeof(vall));
contribution = (contribarr *) Malloc( endsite*sizeof(contribarr));
} /* makeweights */
void prot_makevalues(long categs, pointarray treenode, long endsite,
long spp, sequence y, steptr alias)
{
/* set up fractional likelihoods at tips */
/* a version of makevalues2 found in seq.c */
/* used by proml */
long i, j, k, l;
long b;
for (k = 0; k < endsite; k++) {
j = alias[k];
for (i = 0; i < spp; i++) {
for (l = 0; l < categs; l++) {
memset(treenode[i]->protx[k][l], 0, sizeof(double)*20);
switch (y[i][j - 1]) {
case 'A':
treenode[i]->protx[k][l][0] = 1.0;
break;
case 'R':
treenode[i]->protx[k][l][(long)arginine - (long)alanine] = 1.0;
break;
case 'N':
treenode[i]->protx[k][l][(long)asparagine - (long)alanine] = 1.0;
break;
case 'D':
treenode[i]->protx[k][l][(long)aspartic - (long)alanine] = 1.0;
break;
case 'C':
treenode[i]->protx[k][l][(long)cysteine - (long)alanine] = 1.0;
break;
case 'Q':
treenode[i]->protx[k][l][(long)glutamine - (long)alanine] = 1.0;
break;
case 'E':
treenode[i]->protx[k][l][(long)glutamic - (long)alanine] = 1.0;
break;
case 'G':
treenode[i]->protx[k][l][(long)glycine - (long)alanine] = 1.0;
break;
case 'H':
treenode[i]->protx[k][l][(long)histidine - (long)alanine] = 1.0;
break;
case 'I':
treenode[i]->protx[k][l][(long)isoleucine - (long)alanine] = 1.0;
break;
case 'L':
treenode[i]->protx[k][l][(long)leucine - (long)alanine] = 1.0;
break;
case 'K':
treenode[i]->protx[k][l][(long)lysine - (long)alanine] = 1.0;
break;
case 'M':
treenode[i]->protx[k][l][(long)methionine - (long)alanine] = 1.0;
break;
case 'F':
treenode[i]->protx[k][l][(long)phenylalanine - (long)alanine] = 1.0;
break;
case 'P':
treenode[i]->protx[k][l][(long)proline - (long)alanine] = 1.0;
break;
case 'S':
treenode[i]->protx[k][l][(long)serine - (long)alanine] = 1.0;
break;
case 'T':
treenode[i]->protx[k][l][(long)threonine - (long)alanine] = 1.0;
break;
case 'W':
treenode[i]->protx[k][l][(long)tryptophan - (long)alanine] = 1.0;
break;
case 'Y':
treenode[i]->protx[k][l][(long)tyrosine - (long)alanine] = 1.0;
break;
case 'V':
treenode[i]->protx[k][l][(long)valine - (long)alanine] = 1.0;
break;
case 'B':
treenode[i]->protx[k][l][(long)asparagine - (long)alanine] = 1.0;
treenode[i]->protx[k][l][(long)aspartic - (long)alanine] = 1.0;
break;
case 'Z':
treenode[i]->protx[k][l][(long)glutamine - (long)alanine] = 1.0;
treenode[i]->protx[k][l][(long)glutamic - (long)alanine] = 1.0;
break;
case 'X': /* unknown aa */
for (b = 0; b <= 19; b++)
treenode[i]->protx[k][l][b] = 1.0;
break;
case '?': /* unknown aa */
for (b = 0; b <= 19; b++)
treenode[i]->protx[k][l][b] = 1.0;
break;
case '*': /* stop codon symbol */
for (b = 0; b <= 19; b++)
treenode[i]->protx[k][l][b] = 1.0;
break;
case '-': /* deletion event-absent data or aa */
for (b = 0; b <= 19; b++)
treenode[i]->protx[k][l][b] = 1.0;
break;
}
}
}
}
} /* prot_makevalues */
void getinput()
{
long grcategs;
/* reads the input data */
if (!justwts || firstset)
inputoptions();
if (!justwts || firstset)
input_protdata(seqsets[ith-1],sites);
makeweights();
setuptree2(&curtree);
if (!usertree) {
setuptree2(&bestree);
if (njumble > 1)
setuptree2(&bestree2);
}
grcategs = (categs > rcategs) ? categs : rcategs;
prot_allocx(nonodes, grcategs, curtree.nodep, usertree);
if (!usertree) {
prot_allocx(nonodes, grcategs, bestree.nodep, 0);
if (njumble > 1)
prot_allocx(nonodes, grcategs, bestree2.nodep, 0);
}
prot_makevalues(rcategs, curtree.nodep, endsite, spp, y, alias);
} /* getinput */
void prot_freetable(void)
{
long i,j,k,l;
for (j = 0; j < rcategs; j++) {
for (k = 0; k < categs; k++) {
for (l = 0; l < 20; l++)
free(ddpmatrix[j][k][l]);
free(ddpmatrix[j][k]);
}
free(ddpmatrix[j]);
}
free(ddpmatrix);
for (j = 0; j < rcategs; j++) {
for (k = 0; k < categs; k++) {
for (l = 0; l < 20; l++)
free(dpmatrix[j][k][l]);
free(dpmatrix[j][k]);
}
free(dpmatrix[j]);
}
free(dpmatrix);
for (j = 0; j < rcategs; j++)
free(tbl[j]);
free(tbl);
for ( i = 0 ; i < max_num_sibs ; i++ )
free_pmatrix(i);
free(pmatrices);
} /* prot_freetable */
void prot_inittable()
{
/* Define a lookup table. Precompute values and print them out in tables */
/* Allocate memory for the pmatrices, dpmatices and ddpmatrices */
long i, j, k, l;
double sumrates;
/* Allocate memory for pmatrices, the array of pointers to pmatrices */
pmatrices = (double *****) Malloc (spp * sizeof(double ****));
/* Allocate memory for the first 2 pmatrices, the matrix of conversion */
/* probabilities, but only once per run (aka not on the second jumble. */
alloc_pmatrix(0);
alloc_pmatrix(1);
/* Allocate memory for one dpmatrix, the first derivative matrix */
dpmatrix = (double ****) Malloc( rcategs * sizeof(double ***));
for (j = 0; j < rcategs; j++) {
dpmatrix[j] = (double ***) Malloc( categs * sizeof(double **));
for (k = 0; k < categs; k++) {
dpmatrix[j][k] = (double **) Malloc( 20 * sizeof(double *));
for (l = 0; l < 20; l++)
dpmatrix[j][k][l] = (double *) Malloc( 20 * sizeof(double));
}
}
/* Allocate memory for one ddpmatrix, the second derivative matrix */
ddpmatrix = (double ****) Malloc( rcategs * sizeof(double ***));
for (j = 0; j < rcategs; j++) {
ddpmatrix[j] = (double ***) Malloc( categs * sizeof(double **));
for (k = 0; k < categs; k++) {
ddpmatrix[j][k] = (double **) Malloc( 20 * sizeof(double *));
for (l = 0; l < 20; l++)
ddpmatrix[j][k][l] = (double *) Malloc( 20 * sizeof(double));
}
}
/* Allocate memory and assign values to tbl, the matrix of possible rates*/
tbl = (double **) Malloc( rcategs * sizeof(double *));
for (j = 0; j < rcategs; j++)
tbl[j] = (double *) Malloc( categs * sizeof(double));
for (j = 0; j < rcategs; j++)
for (k = 0; k < categs; k++)
tbl[j][k] = rrate[j]*rate[k];
sumrates = 0.0;
for (i = 0; i < endsite; i++) {
for (j = 0; j < rcategs; j++)
sumrates += aliasweight[i] * probcat[j]
* tbl[j][category[alias[i] - 1] - 1];
}
sumrates /= (double)sites;
for (j = 0; j < rcategs; j++)
for (k = 0; k < categs; k++) {
tbl[j][k] /= sumrates;
}
if(jumb > 1)
return;
if (gama || invar) {
fprintf(outfile, "\nDiscrete approximation to gamma distributed rates\n");
fprintf(outfile,
" Coefficient of variation of rates = %f (alpha = %f)\n", cv, alpha);
}
if (rcategs > 1) {
fprintf(outfile, "\nState in HMM Rate of change Probability\n\n");
for (i = 0; i < rcategs; i++)
if (probcat[i] < 0.0001)
fprintf(outfile, "%9ld%16.3f%20.6f\n", i+1, rrate[i], probcat[i]);
else if (probcat[i] < 0.001)
fprintf(outfile, "%9ld%16.3f%19.5f\n", i+1, rrate[i], probcat[i]);
else if (probcat[i] < 0.01)
fprintf(outfile, "%9ld%16.3f%18.4f\n", i+1, rrate[i], probcat[i]);
else
fprintf(outfile, "%9ld%16.3f%17.3f\n", i+1, rrate[i], probcat[i]);
putc('\n', outfile);
if (auto_) {
fprintf(outfile,
"Expected length of a patch of sites having the same rate = %8.3f\n",
1/lambda);
putc('\n', outfile);
}
}
if (categs > 1) {
fprintf(outfile, "\nSite category Rate of change\n\n");
for (k = 0; k < categs; k++)
fprintf(outfile, "%9ld%16.3f\n", k+1, rate[k]);
fprintf(outfile, "\n\n");
}
} /* prot_inittable */
void free_pmatrix(long sib)
{
long j,k,l;
for (j = 0; j < rcategs; j++) {
for (k = 0; k < categs; k++) {
for (l = 0; l < 20; l++)
free(pmatrices[sib][j][k][l]);
free(pmatrices[sib][j][k]);
}
free(pmatrices[sib][j]);
}
free(pmatrices[sib]);
} /* free_pmatrix */
void alloc_pmatrix(long sib)
{
/* Allocate memory for a new pmatrix. Called iff num_sibs>max_num_sibs */
long j, k, l;
double ****temp_matrix;
temp_matrix = (double ****) Malloc (rcategs * sizeof(double ***));
for (j = 0; j < rcategs; j++) {
temp_matrix[j] = (double ***) Malloc(categs * sizeof(double **));
for (k = 0; k < categs; k++) {
temp_matrix[j][k] = (double **) Malloc(20 * sizeof (double *));
for (l = 0; l < 20; l++)
temp_matrix[j][k][l] = (double *) Malloc(20 * sizeof(double));
}
}
pmatrices[sib] = temp_matrix;
max_num_sibs++;
} /* alloc_pmatrix */
void make_pmatrix(double **matrix, double **dmat, double **ddmat,
long derivative, double lz, double rat,
double *eigmat, double **probmat)
{
/* Computes the R matrix such that matrix[m][l] is the joint probability */
/* of m and l. */
/* Computes a P matrix such that matrix[m][l] is the conditional */
/* probability of m given l. This is accomplished by dividing all terms */
/* in the R matrix by freqaa[m], the frequency of l. */
long k, l, m; /* (l) original character state */
/* (m) final character state */
/* (k) lambda counter */
double p0, p1, p2, q;
double elambdat[20], delambdat[20], ddelambdat[20];
/* exponential term for matrix */
/* and both derivative matrices */
for (k = 0; k <= 19; k++) {
elambdat[k] = exp(lz * rat * eigmat[k]);
if(derivative != 0) {
delambdat[k] = (elambdat[k] * rat * eigmat[k]);
ddelambdat[k] = (delambdat[k] * rat * eigmat[k]);
}
}
for (m = 0; m <= 19; m++) {
for (l = 0; l <= 19; l++) {
p0 = 0.0;
p1 = 0.0;
p2 = 0.0;
for (k = 0; k <= 19; k++) {
q = probmat[k][m] * probmat[k][l];
p0 += (q * elambdat[k]);
if(derivative !=0) {
p1 += (q * delambdat[k]);
p2 += (q * ddelambdat[k]);
}
}
matrix[m][l] = p0 / freqaa[m];
if(derivative != 0) {
dmat[m][l] = p1 / freqaa[m];
ddmat[m][l] = p2 / freqaa[m];
}
}
}
} /* make_pmatrix */
boolean prot_nuview(node *p)
{
/* Recursively update summary data for subtree rooted at p. Returns true if
* view has changed. */
long i, j, k, l, num_sibs = 0, sib_index;
long b, m;
node *q;
node *sib_ptr, *sib_back_ptr;
psitelike prot_xx, x2;
double prod7;
double **pmat;
double lw;
double correction;
double maxx;
if ( p == NULL ) return false;
if ( p->tip ) return false; /* Tips do not need to be initialized */
for (q = p->next; q != p; q = q->next) {
num_sibs++;
if ( q->back != NULL && !q->tip) {
if ( prot_nuview(q->back) )
p->initialized = false;
}
}
if ( p->initialized )
return false;
/* Make sure pmatrices is large enough for all siblings */
for (i = 0; i < num_sibs; i++)
if (pmatrices[i] == NULL)
alloc_pmatrix(i);
/* Make pmatrices for all possible combinations of category, rcateg */
/* and sib */
sib_ptr = p; /* return to p */
for (sib_index=0; sib_index < num_sibs; sib_index++) {
sib_ptr = sib_ptr->next;
sib_back_ptr = sib_ptr->back;
if (sib_back_ptr != NULL)
lw = fabs(p->tyme - sib_back_ptr->tyme);
else
lw = 0.0;
for (j = 0; j < rcategs; j++)
for (k = 0; k < categs; k++)
make_pmatrix(pmatrices[sib_index][j][k], NULL, NULL, 0, lw,
tbl[j][k], eigmat, probmat);
}
for (i = 0; i < endsite; i++) {
correction = 0;
maxx = 0;
k = category[alias[i]-1] - 1;
for (j = 0; j < rcategs; j++) {
/* initialize to 1 all values of prot_xx */
for (m = 0; m <= 19; m++)
prot_xx[m] = 1;
sib_ptr = p; /* return to p */
/* loop through all sibs and calculate likelihoods for all possible*/
/* amino acid combinations */
for (sib_index=0; sib_index < num_sibs; sib_index++) {
sib_ptr = sib_ptr->next;
sib_back_ptr = sib_ptr->back;
if (sib_back_ptr != NULL) {
memcpy(x2, sib_back_ptr->protx[i][j], sizeof(psitelike));
if ( j == 0 )
correction += sib_back_ptr->underflows[i];
}
else
for (b = 0; b <= 19; b++)
x2[b] = 1.0;
pmat = pmatrices[sib_index][j][k];
for (m = 0; m <= 19; m++) {
prod7 = 0;
for (l = 0; l <= 19; l++)
prod7 += (pmat[m][l] * x2[l]);
prot_xx[m] *= prod7;
if ( prot_xx[m] > maxx && sib_index == (num_sibs - 1 ))
maxx = prot_xx[m];
}
}
/* And the final point of this whole function: */
memcpy(p->protx[i][j], prot_xx, sizeof(psitelike));
}
p->underflows[i] = 0;
if ( maxx < MIN_DOUBLE )
fix_protx(p,i,maxx,rcategs);
p->underflows[i] += correction;
}
p->initialized = true;
return true;
} /* prot_nuview */
void update(node *p)
{
node *sib_ptr, *sib_back_ptr;
long i, num_sibs;
/* improve time and recompute views at a node */
if (p == NULL)
return;
if (p->back != NULL) {
if (!p->back->tip && !p->back->initialized)
prot_nuview(p->back);
}
sib_ptr = p;
num_sibs = count_sibs(p);
for (i=0 ; i < num_sibs; i++) {
sib_ptr = sib_ptr->next;
sib_back_ptr = sib_ptr->back;
if (sib_back_ptr != NULL) {
if (!sib_back_ptr->tip && !sib_back_ptr->initialized)
prot_nuview(sib_back_ptr);
}
}
if ( (!usertree) || (usertree && !lngths) ) {
mnv_success = makenewv(p) || mnv_success;
return;
}
prot_nuview(p);
sib_ptr = p;
num_sibs = count_sibs(p);
for (i=0 ; i < num_sibs; i++) {
sib_ptr = sib_ptr->next;
prot_nuview(sib_ptr);
}
} /* update */
void smooth(node *p)
{
node *q;
if (p == NULL)
return;
if (p->tip)
return;
/* optimize tyme here */
update(p);
if (smoothit || polishing) {
for (q = p->next; q != p; q = q->next) {
if (!q->back->tip) {
/* smooth subtrees */
smooth(q->back);
/* optimize tyme again after each subtree */
update(p);
}
}
}
} /* smooth */
void promlk_add(node *below, node *newtip, node *newfork, boolean tempadd)
{
/* inserts the nodes newfork and its descendant, newtip, into the tree. */
long i;
boolean done;
node *p;
double newtyme;
/* Get parent nodelets */
below = curtree.nodep[below->index - 1];
newfork = curtree.nodep[newfork->index-1];
newtip = curtree.nodep[newtip->index-1];
/* Join above node to newfork */
if (below->back != NULL)
below->back->back = newfork;
newfork->back = below->back;
/* Join below to newfork->next->next */
below->back = newfork->next->next;
newfork->next->next->back = below;
/* Join newtip to newfork->next */
newfork->next->back = newtip;
newtip->back = newfork->next;
/* assign newfork minimum child tyme */
if (newtip->tyme < below->tyme)
p = newtip;
else
p = below;
newtyme = p->tyme;
setnodetymes(newfork,newtyme);
/* Move root if inserting there */
if (curtree.root == below)
curtree.root = newfork;
/* If not at root, set newfork tyme to average below/above */
if (newfork->back != NULL) {
if (p->tyme > newfork->back->tyme)
newtyme = (p->tyme + newfork->back->tyme) / 2.0;
else
newtyme = p->tyme - INSERT_MIN_TYME;
setnodetymes(newfork, newtyme);
/* Now move from p to root, setting parent tymes older than children
* by at least INSERT_MIN_TYME */
do {
p = curtree.nodep[p->back->index - 1];
done = (p == curtree.root);
if (!done)
done = (curtree.nodep[p->back->index - 1]->tyme < p->tyme - INSERT_MIN_TYME);
if (!done) {
setnodetymes(curtree.nodep[p->back->index - 1], p->tyme - INSERT_MIN_TYME);
}
} while (!done);
} else { /* root == newfork */
/* make root 2x older */
setnodetymes(newfork, newfork->tyme - 2*INSERT_MIN_TYME);
}
/* This is needed to prevent negative lengths */
all_tymes_valid(curtree.root, 0.0, true);
/* Invalidate views */
inittrav(newtip);
inittrav(newtip->back);
/* Adjust branch lengths throughout */
for ( i = 1; i < smoothings; i++ ) {
smoothed = true;
smooth(newfork);
smooth(newfork->back);
if ( smoothed ) break;
}
} /* promlk_add */
void promlk_re_move(node **item, node **fork, boolean tempadd)
{
/* removes nodes item and its ancestor, fork, from the tree.
the new descendant of fork's ancestor is made to be
fork's second descendant (other than item). Also
returns pointers to the deleted nodes, item and fork */
node *p, *q;
long i;
if ((*item)->back == NULL) {
*fork = NULL;
return;
}
*item = curtree.nodep[(*item)->index-1];
*fork = curtree.nodep[(*item)->back->index - 1];
if (curtree.root == *fork) {
if (*item == (*fork)->next->back)
curtree.root = (*fork)->next->next->back;
else
curtree.root = (*fork)->next->back;
}
p = (*item)->back->next->back;
q = (*item)->back->next->next->back;
if (p != NULL)
p->back = q;
if (q != NULL)
q->back = p;
(*fork)->back = NULL;
p = (*fork)->next;
while (p != *fork) {
p->back = NULL;
p = p->next;
}
(*item)->back = NULL;
inittrav(p);
inittrav(q);
if (tempadd)
return;
/* This is needed to prevent negative lengths */
all_tymes_valid(curtree.root, 0.0, true);
i = 1;
while (i <= smoothings) {
smooth(q);
if (smoothit)
smooth(q->back);
i++;
}
} /* promlk_re_move */
double prot_evaluate(node *p)
{ /* Evaluate and return the log likelihood of the current tree
* as seen from the branch from p to p->back. If p is the root node,
* the first child branch is used instead. Views are updated as needed. */
contribarr tterm;
static contribarr like, nulike, clai;
double sum, sum2, sumc=0, y, prod4, prodl, frexm, sumterm, lterm;
double **pmat;
long i, j, k, l, m, lai;
node *q, *r;
psitelike x1, x2;
sum = 0.0;
if (p == curtree.root) {
p = p->next;
}
r = p;
q = p->back;
prot_nuview (r);
prot_nuview (q);
y = fabs(r->tyme - q->tyme);
for (j = 0; j < rcategs; j++)
for (k = 0; k < categs; k++)
make_pmatrix(pmatrices[0][j][k],NULL,NULL,0,y,tbl[j][k],eigmat,probmat);
for (i = 0; i < endsite; i++) {
k = category[alias[i]-1] - 1;
for (j = 0; j < rcategs; j++) {
memcpy(x1, r->protx[i][j], sizeof(psitelike));
memcpy(x2, q->protx[i][j], sizeof(psitelike));
prod4 = 0.0;
pmat = pmatrices[0][j][k];
for (m = 0; m <= 19; m++) {
prodl = 0.0;
for (l = 0; l <= 19; l++)
prodl += (pmat[m][l] * x2[l]);
frexm = x1[m] * freqaa[m];
prod4 += (prodl * frexm);
}
tterm[j] = prod4;
}
sumterm = 0.0;
for (j = 0; j < rcategs; j++)
sumterm += probcat[j] * tterm[j];
if (sumterm < 0.0)
sumterm = 0.00000001; /* ??? */
lterm = log(sumterm) + p->underflows[i] + q->underflows[i];
for (j = 0; j < rcategs; j++)
clai[j] = tterm[j] / sumterm;
memcpy(contribution[i], clai, rcategs * sizeof(double));
if (!auto_ && usertree && (which <= shimotrees))
l0gf[which - 1][i] = lterm;
sum += aliasweight[i] * lterm;
}
if (auto_) {
for (j = 0; j < rcategs; j++)
like[j] = 1.0;
for (i = 0; i < sites; i++) {
sumc = 0.0;
for (k = 0; k < rcategs; k++)
sumc += probcat[k] * like[k];
sumc *= lambda;
if ((ally[i] > 0) && (location[ally[i]-1] > 0)) {
lai = location[ally[i] - 1];
memcpy(clai, contribution[lai - 1], rcategs*sizeof(double));
for (j = 0; j < rcategs; j++)
nulike[j] = ((1.0 - lambda) * like[j] + sumc) * clai[j];
} else {
for (j = 0; j < rcategs; j++)
nulike[j] = ((1.0 - lambda) * like[j] + sumc);
}
memcpy(like, nulike, rcategs * sizeof(double));
}
sum2 = 0.0;
for (i = 0; i < rcategs; i++)
sum2 += probcat[i] * like[i];
sum += log(sum2);
}
/* FIXME check sum for -inf or nan
* (sometimes occurs with short branches) */
assert( sum - sum == 0.0 );
curtree.likelihood = sum;
if (auto_ || !usertree)
return sum;
if(which <= shimotrees)
l0gl[which - 1] = sum;
if (which == 1) {
maxwhich = 1;
maxlogl = sum;
return sum;
}
if (sum > maxlogl) {
maxwhich = which;
maxlogl = sum;
}
return sum;
} /* prot_evaluate */
void tryadd(node *p, node **item, node **nufork)
{ /* temporarily adds one fork and one tip to the tree.
if the location where they are added yields greater
likelihood than other locations tested up to that
time, then keeps that location as there */
long grcategs;
grcategs = (categs > rcategs) ? categs : rcategs;
promlk_add(p, *item, *nufork, true);
like = prot_evaluate(p);
if (lastsp) {
if (like >= bestyet || bestyet == UNDEFINED)
prot_copy_(&curtree, &bestree, nonodes, grcategs);
}
if (like > bestyet || bestyet == UNDEFINED) {
bestyet = like;
there = p;
}
promlk_re_move(item, nufork, true);
} /* tryadd */
void addpreorder(node *p, node *item, node *nufork, boolean contin)
{
/* traverses a binary tree, calling function tryadd
at a node before calling tryadd at its descendants */
if (p == NULL)
return;
tryadd(p, &item, &nufork);
if ((!p->tip) && contin) {
addpreorder(p->next->back, item, nufork, contin);
addpreorder(p->next->next->back, item, nufork, contin);
}
} /* addpreorder */
void restoradd(node *below, node *newtip, node *newfork, double prevtyme)
{
/* restore "new" tip and fork to place "below". restore tymes */
/* assumes bifurcation */
hookup(newfork, below->back);
hookup(newfork->next, below);
hookup(newtip, newfork->next->next);
curtree.nodep[newfork->index-1] = newfork;
newfork->tyme = prevtyme;
/* assumes bifurcations */
newfork->next->tyme = prevtyme;
newfork->next->next->tyme = prevtyme;
} /* restoradd */
void tryrearr(node *p, boolean *success)
{
/* evaluates one rearrangement of the tree.
if the new tree has greater likelihood than the old
one sets success = TRUE and keeps the new tree.
otherwise, restores the old tree */
node *frombelow, *whereto, *forknode;
double oldlike, prevtyme;
boolean wasonleft;
if (p == curtree.root)
return;
forknode = curtree.nodep[p->back->index - 1];
if (forknode == curtree.root)
return;
oldlike = bestyet;
prevtyme = forknode->tyme;
/* the following statement presumes bifurcating tree */
if (forknode->next->back == p) {
frombelow = forknode->next->next->back;
wasonleft = true;
}
else {
frombelow = forknode->next->back;
wasonleft = false;
}
whereto = curtree.nodep[forknode->back->index - 1];
promlk_re_move(&p, &forknode, true);
promlk_add(whereto, p, forknode, true);
like = prot_evaluate(p);
if (like - oldlike > LIKE_EPSILON || oldlike == UNDEFINED) {
(*success) = true;
bestyet = like;
}
else {
promlk_re_move(&p, &forknode, true);
restoradd(frombelow, p, forknode, prevtyme);
if (wasonleft && (forknode->next->next->back == p)) {
hookup (forknode->next->back, forknode->next->next);
hookup (forknode->next, p);
}
curtree.likelihood = oldlike;
/* assumes bifurcation */
inittrav(forknode);
inittrav(forknode->next);
inittrav(forknode->next->next);
}
} /* tryrearr */
void repreorder(node *p, boolean *success)
{
/* traverses a binary tree, calling function tryrearr
at a node before calling tryrearr at its descendants */
if (p == NULL)
return;
tryrearr(p, success);
if (p->tip)
return;
if (!(*success))
repreorder(p->next->back, success);
if (!(*success))
repreorder(p->next->next->back, success);
} /* repreorder */
void rearrange(node **r)
{
/* traverses the tree (preorder), finding any local
rearrangement which increases the likelihood.
if traversal succeeds in increasing the tree's
likelihood, function rearrange runs traversal again */
boolean success;
success = true;
while (success) {
success = false;
repreorder(*r, &success);
}
} /* rearrange */
void nodeinit(node *p)
{
/* set up times at one node */
node *sib_ptr, *sib_back_ptr;
long i, num_sibs;
double lowertyme;
sib_ptr = p;
num_sibs = count_sibs(p);
/* lowertyme = lowest of children's times */
lowertyme = p->next->back->tyme;
for (i=0 ; i < num_sibs; i++) {
sib_ptr = sib_ptr->next;
sib_back_ptr = sib_ptr->back;
if (sib_back_ptr->tyme < lowertyme)
lowertyme = sib_back_ptr->tyme;
}
p->tyme = lowertyme - 0.1;
sib_ptr = p;
for (i=0 ; i < num_sibs; i++) {
sib_ptr = sib_ptr->next;
sib_back_ptr = sib_ptr->back;
sib_ptr->tyme = p->tyme;
sib_back_ptr->v = sib_back_ptr->tyme - p->tyme;
sib_ptr->v = sib_back_ptr->v;
}
} /* nodeinit */
void invalidate_traverse(node *p)
{ /* Invalidates p's view and all views looking toward p from p->back
* on out. */
node *q;
if (p == NULL)
return;
if (p->tip)
return;
p->initialized = false;
q = p->back;
if ( q == NULL ) return;
if ( q->tip ) return;
/* Call ourselves on p->back's sibs */
for ( q = q->next ; q != p->back ; q = q->next) {
invalidate_traverse(q);
}
} /* invalidate_traverse */
void invalidate_tyme(node *p) {
/* Must be called on a node after changing its tyme, and before calling
* evaluate on any other node. */
node *q;
if ( p == NULL )
return;
invalidate_traverse(p);
if ( p->tip )
return;
for ( q = p->next; q != p; q = q->next ) {
invalidate_traverse(q);
}
} /* invalidate_tyme */
void initrav(node *p)
{
long i, num_sibs;
node *sib_ptr, *sib_back_ptr;
/* traverse to set up times throughout tree */
if (p->tip)
return;
sib_ptr = p;
num_sibs = count_sibs(p);
for (i=0 ; i < num_sibs; i++) {
sib_ptr = sib_ptr->next;
sib_back_ptr = sib_ptr->back;
initrav(sib_back_ptr);
}
nodeinit(p);
} /* initrav */
void travinit(node *p)
{
long i, num_sibs;
node *sib_ptr, *sib_back_ptr;
/* traverse to set up initial values */
if (p == NULL)
return;
if (p->tip)
return;
if (p->initialized)
return;
sib_ptr = p;
num_sibs = count_sibs(p);
for (i=0 ; i < num_sibs; i++) {
sib_ptr = sib_ptr->next;
sib_back_ptr = sib_ptr->back;
travinit(sib_back_ptr);
}
prot_nuview(p);
p->initialized = true;
} /* travinit */
void travsp(node *p)
{
long i, num_sibs;
node *sib_ptr, *sib_back_ptr;
/* traverse to find tips */
if (p == curtree.root)
travinit(p);
if (p->tip)
travinit(p->back);
else {
sib_ptr = p;
num_sibs = count_sibs(p);
for (i=0 ; i < num_sibs; i++) {
sib_ptr = sib_ptr->next;
sib_back_ptr = sib_ptr->back;
travsp(sib_back_ptr);
}
}
} /* travsp */
void treevaluate()
{
/* evaluate likelihood of tree, after iterating branch lengths */
long i, j, num_sibs;
node *sib_ptr;
polishing = true;
smoothit = true;
for (i = 0; i < spp; i++)
curtree.nodep[i]->initialized = false;
for (i = spp; i < nonodes; i++) {
sib_ptr = curtree.nodep[i];
sib_ptr->initialized = false;
num_sibs = count_sibs(sib_ptr);
for (j=0 ; j < num_sibs; j++) {
sib_ptr = sib_ptr->next;
sib_ptr->initialized = false;
}
}
if (!lngths)
initrav(curtree.root);
travsp(curtree.root);
i = 0;
do {
mnv_success = false;
smooth(curtree.root);
i++;
} while (mnv_success);
prot_evaluate(curtree.root);
} /* treevaluate */
void prot_reconstr(node *p, long n)
{
/* reconstruct and print out acid at site n+1 at node p */
long i, j, k, first, num_sibs = 0;
double f, sum, xx[20];
node *q = NULL;
if (p->tip)
putc(y[p->index-1][n], outfile);
else {
num_sibs = count_sibs(p);
if ((ally[n] == 0) || (location[ally[n]-1] == 0))
putc('.', outfile);
else {
j = location[ally[n]-1] - 1;
sum = 0;
for (i = 0; i <= 19; i++) {
f = p->protx[j][mx-1][i];
if (!p->tip) {
q = p;
for (k = 0; k < num_sibs; k++) {
q = q->next;
f *= q->protx[j][mx-1][i];
}
}
f = sqrt(f);
xx[i] = f * freqaa[i];
sum += xx[i];
}
for (i = 0; i <= 19; i++)
xx[i] /= sum;
first = 0;
for (i = 0; i <= 19; i++)
if (xx[i] > xx[first])
first = i;
if (xx[first] > 0.95)
putc(aachar[first], outfile);
else
putc(tolower((int)aachar[first]), outfile);
if (rctgry && rcategs > 1)
mx = mp[n][mx - 1];
else
mx = 1;
}
}
} /* prot_reconstr */
void rectrav(node *p, long m, long n)
{
/* print out segment of reconstructed sequence for one branch */
long num_sibs, i;
node *sib_ptr;
putc(' ', outfile);
if (p->tip) {
for (i = 0; i < nmlngth; i++)
putc(nayme[p->index-1][i], outfile);
} else
fprintf(outfile, "%4ld ", p->index - spp);
fprintf(outfile, " ");
mx = mx0;
for (i = m; i <= n; i++) {
if ((i % 10 == 0) && (i != m))
putc(' ', outfile);
prot_reconstr(p, i);
}
putc('\n', outfile);
if (!p->tip) {
num_sibs = count_sibs(p);
sib_ptr = p;
for (i = 0; i < num_sibs; i++) {
sib_ptr = sib_ptr->next;
rectrav(sib_ptr->back, m, n);
}
}
mx1 = mx;
} /* rectrav */
void summarize()
{
long i, j, mm=0;
double mode, sum;
double like[maxcategs], nulike[maxcategs];
double **marginal;
long **mp;
mp = (long **)Malloc(sites * sizeof(long *));
for (i = 0; i <= sites-1; ++i)
mp[i] = (long *)Malloc(sizeof(long)*rcategs);
fprintf(outfile, "\nLn Likelihood = %11.5f\n\n", curtree.likelihood);
fprintf(outfile, " Ancestor Node Node Height Length\n");
fprintf(outfile, " -------- ---- ---- ------ ------\n");
mlk_describe(outfile, &curtree, 1.0);
putc('\n', outfile);
if (rctgry && rcategs > 1) {
for (i = 0; i < rcategs; i++)
like[i] = 1.0;
for (i = sites - 1; i >= 0; i--) {
sum = 0.0;
for (j = 0; j < rcategs; j++) {
nulike[j] = (lambda1 + lambda * probcat[j]) * like[j];
mp[i][j] = j + 1;
for (k = 1; k <= rcategs; k++) {
if (k != j + 1) {
if (lambda * probcat[k - 1] * like[k - 1] > nulike[j]) {
nulike[j] = lambda * probcat[k - 1] * like[k - 1];
mp[i][j] = k;
}
}
}
if ((ally[i] > 0) && (location[ally[i]-1] > 0))
nulike[j] *= contribution[location[ally[i] - 1] - 1][j];
sum += nulike[j];
}
for (j = 0; j < rcategs; j++)
nulike[j] /= sum;
memcpy(like, nulike, rcategs * sizeof(double));
}
mode = 0.0;
mx = 1;
for (i = 1; i <= rcategs; i++) {
if (probcat[i - 1] * like[i - 1] > mode) {
mx = i;
mode = probcat[i - 1] * like[i - 1];
}
}
mx0 = mx;
fprintf(outfile,
"Combination of categories that contributes the most to the likelihood:\n\n");
for (i = 1; i <= nmlngth + 3; i++)
putc(' ', outfile);
for (i = 1; i <= sites; i++) {
fprintf(outfile, "%ld", mx);
if (i % 10 == 0)
putc(' ', outfile);
if (i % 60 == 0 && i != sites) {
putc('\n', outfile);
for (j = 1; j <= nmlngth + 3; j++)
putc(' ', outfile);
}
mx = mp[i - 1][mx - 1];
}
fprintf(outfile, "\n\n");
marginal = (double **) Malloc( sites*sizeof(double *));
for (i = 0; i < sites; i++)
marginal[i] = (double *) Malloc( rcategs*sizeof(double));
for (i = 0; i < rcategs; i++)
like[i] = 1.0;
for (i = sites - 1; i >= 0; i--) {
sum = 0.0;
for (j = 0; j < rcategs; j++) {
nulike[j] = (lambda1 + lambda * probcat[j]) * like[j];
for (k = 1; k <= rcategs; k++) {
if (k != j + 1)
nulike[j] += lambda * probcat[k - 1] * like[k - 1];
}
if ((ally[i] > 0) && (location[ally[i]-1] > 0))
nulike[j] *= contribution[location[ally[i] - 1] - 1][j];
sum += nulike[j];
}
for (j = 0; j < rcategs; j++) {
nulike[j] /= sum;
marginal[i][j] = nulike[j];
}
memcpy(like, nulike, rcategs * sizeof(double));
}
for (i = 0; i < rcategs; i++)
like[i] = 1.0;
for (i = 0; i < sites; i++) {
sum = 0.0;
for (j = 0; j < rcategs; j++) {
nulike[j] = (lambda1 + lambda * probcat[j]) * like[j];
for (k = 1; k <= rcategs; k++) {
if (k != j + 1)
nulike[j] += lambda * probcat[k - 1] * like[k - 1];
}
marginal[i][j] *= like[j] * probcat[j];
sum += nulike[j];
}
for (j = 0; j < rcategs; j++)
nulike[j] /= sum;
memcpy(like, nulike, rcategs * sizeof(double));
sum = 0.0;
for (j = 0; j < rcategs; j++)
sum += marginal[i][j];
for (j = 0; j < rcategs; j++)
marginal[i][j] /= sum;
}
fprintf(outfile, "Most probable category at each site if > 0.95");
fprintf(outfile, " probability (\".\" otherwise)\n\n");
for (i = 1; i <= nmlngth + 3; i++)
putc(' ', outfile);
for (i = 0; i < sites; i++) {
sum = 0.0;
mm = 0;
for (j = 0; j < rcategs; j++)
if (marginal[i][j] > sum) {
sum = marginal[i][j];
mm = j;
}
if (sum >= 0.95)
fprintf(outfile, "%ld", mm+1);
else
putc('.', outfile);
if ((i+1) % 60 == 0) {
if (i != 0) {
putc('\n', outfile);
for (j = 1; j <= nmlngth + 3; j++)
putc(' ', outfile);
}
}
else if ((i+1) % 10 == 0)
putc(' ', outfile);
}
putc('\n', outfile);
for (i = 0; i < sites; i++)
free(marginal[i]);
free(marginal);
}
for (i = 0; i <= sites-1; ++i)
free(mp[i]);
free(mp);
putc('\n', outfile);
putc('\n', outfile);
putc('\n', outfile);
if (hypstate) {
fprintf(outfile, "Probable sequences at interior nodes:\n\n");
fprintf(outfile, " node ");
for (i = 0; (i < 13) && (i < ((sites + (sites-1)/10 - 39) / 2)); i++)
putc(' ', outfile);
fprintf(outfile, "Reconstructed sequence (caps if > 0.95)\n\n");
if (!rctgry || (rcategs == 1))
mx0 = 1;
for (i = 0; i < sites; i += 60) {
k = i + 59;
if (k >= sites)
k = sites - 1;
rectrav(curtree.root, i, k);
putc('\n', outfile);
mx0 = mx1;
}
}
} /* summarize */
void promlk_treeout(node *p)
{
/* write out file with representation of final tree */
node *sib_ptr;
long i, n, w, num_sibs;
Char c;
double x;
if (p->tip) {
n = 0;
for (i = 1; i <= nmlngth; i++) {
if (nayme[p->index - 1][i - 1] != ' ')
n = i;
}
for (i = 0; i < n; i++) {
c = nayme[p->index - 1][i];
if (c == ' ')
c = '_';
putc(c, outtree);
}
col += n;
} else {
sib_ptr = p;
num_sibs = count_sibs(p);
putc('(', outtree);
col++;
for (i=0; i < (num_sibs - 1); i++) {
sib_ptr = sib_ptr->next;
promlk_treeout(sib_ptr->back);
putc(',', outtree);
col++;
if (col > 55) {
putc('\n', outtree);
col = 0;
}
}
sib_ptr = sib_ptr->next;
promlk_treeout(sib_ptr->back);
putc(')', outtree);
col++;
}
if (p == curtree.root) {
fprintf(outtree, ";\n");
return;
}
x = (p->tyme - curtree.nodep[p->back->index - 1]->tyme);
if (x > 0.0)
w = (long)(0.4342944822 * log(x));
else if (x == 0.0)
w = 0;
else
w = (long)(0.4342944822 * log(-x)) + 1;
if (w < 0)
w = 0;
fprintf(outtree, ":%*.5f", (int)(w + 7), x);
col += w + 8;
} /* promlk_treeout */
void initpromlnode(node **p, node **grbg, node *q, long len, long nodei,
long *ntips, long *parens, initops whichinit,
pointarray treenode, pointarray nodep, Char *str,
Char *ch, char **treestr)
{
/* initializes a node */
boolean minusread;
double valyew, divisor;
switch (whichinit) {
case bottom:
gnu(grbg, p);
(*p)->index = nodei;
(*p)->tip = false;
malloc_ppheno((*p), endsite, rcategs);
nodep[(*p)->index - 1] = (*p);
break;
case nonbottom:
gnu(grbg, p);
malloc_ppheno(*p, endsite, rcategs);
(*p)->index = nodei;
break;
case tip:
match_names_to_data(str, nodep, p, spp);
break;
case iter:
(*p)->initialized = false;
(*p)->v = initialv;
(*p)->iter = true;
if ((*p)->back != NULL)
(*p)->back->iter = true;
break;
case length:
processlength(&valyew, &divisor, ch, &minusread, treestr, parens);
(*p)->v = valyew / divisor;
(*p)->iter = false;
if ((*p)->back != NULL) {
(*p)->back->v = (*p)->v;
(*p)->back->iter = false;
}
break;
case hsnolength:
if (usertree && lngths) {
printf("Warning: one or more lengths not defined in user tree number %ld.\n", which);
printf("PROMLK will attempt to optimize all branch lengths.\n\n");
lngths = false;
}
break;
case unittrwt:
curtree.nodep[spp]->iter = false;
break;
default: /* cases hslength, treewt */
break; /* should never occur */
}
} /* initpromlnode */
void tymetrav(node *p, double *x)
{
/* set up times of nodes */
node *sib_ptr, *q;
long i, num_sibs;
double xmax;
xmax = 0.0;
if (!p->tip) {
sib_ptr = p;
num_sibs = count_sibs(p);
for (i=0; i < num_sibs; i++) {
sib_ptr = sib_ptr->next;
tymetrav(sib_ptr->back, x);
if (xmax > (*x))
xmax = (*x);
}
} else
(*x) = 0.0;
p->tyme = xmax;
if (!p->tip) {
q = p;
while (q->next != p) {
q = q->next;
q->tyme = p->tyme;
}
}
(*x) = p->tyme - p->v;
} /* tymetrav */
void free_all_protx (long nonodes, pointarray treenode)
{
/* used in proml */
long i, j, k;
node *p;
/* Zero thru spp are tips, */
for (i = 0; i < spp; i++) {
for (j = 0; j < endsite; j++)
free(treenode[i]->protx[j]);
free(treenode[i]->protx);
}
/* The rest are rings (i.e. triads) */
for (i = spp; i < nonodes; i++) {
if (treenode[i] != NULL) {
p = treenode[i];
for (j = 1; j <= 3; j++) {
for (k = 0; k < endsite; k++)
free(p->protx[k]);
free(p->protx);
p = p->next;
}
}
}
} /* free_all_protx */
void maketree()
{
/* constructs a binary tree from the pointers in curtree.nodep,
adds each node at location which yields highest likelihood
then rearranges the tree for greatest likelihood */
long i, j;
long numtrees = 0;
double bestlike, gotlike, x;
node *item, *nufork, *dummy, *q, *root=NULL;
boolean dummy_haslengths, dummy_first, goteof;
long max_nonodes; /* Maximum number of nodes required to
* express all species in a bifurcating tree
* */
long nextnode;
long grcategs;
pointarray dummy_treenode=NULL;
char *treestr;
grcategs = (categs > rcategs) ? categs : rcategs;
prot_inittable();
if (!usertree) {
for (i = 1; i <= spp; i++)
enterorder[i - 1] = i;
if (jumble)
randumize(seed, enterorder);
curtree.root = curtree.nodep[spp];
curtree.root->back = NULL;
for (i = 0; i < spp; i++)
curtree.nodep[i]->back = NULL;
for (i = spp; i < nonodes; i++) {
q = curtree.nodep[i];
q->back = NULL;
while ((q = q->next) != curtree.nodep[i])
q->back = NULL;
}
polishing = false;
promlk_add(curtree.nodep[enterorder[0]-1], curtree.nodep[enterorder[1]-1],
curtree.nodep[spp], false);
if (progress) {
printf("\nAdding species:\n");
writename(0, 2, enterorder);
#ifdef WIN32
phyFillScreenColor();
#endif
}
lastsp = false;
smoothit = false;
for (i = 3; i <= spp; i++) {
bestree.likelihood = UNDEFINED;
bestyet = UNDEFINED;
there = curtree.root;
item = curtree.nodep[enterorder[i - 1] - 1];
nufork = curtree.nodep[spp + i - 2];
lastsp = (i == spp);
addpreorder(curtree.root, item, nufork, true);
promlk_add(there, item, nufork, false);
like = prot_evaluate(curtree.root);
rearrange(&curtree.root);
if (curtree.likelihood > bestree.likelihood) {
prot_copy_(&curtree, &bestree, nonodes, grcategs);
}
if (progress) {
writename(i - 1, 1, enterorder);
#ifdef WIN32
phyFillScreenColor();
#endif
}
if (lastsp && global) {
if (progress) {
printf("Doing global rearrangements\n");
printf(" !");
for (j = 1; j <= nonodes; j++)
if ( j % (( nonodes / 72 ) + 1 ) == 0 )
putchar('-');
fprintf(outfile, "!\n");
}
bestlike = bestyet;
do {
if (progress)
printf(" ");
gotlike = bestlike;
for (j = 0; j < nonodes; j++) {
bestyet = UNDEFINED;
item = curtree.nodep[j];
if (item != curtree.root) {
nufork = curtree.nodep[curtree.nodep[j]->back->index - 1];
promlk_re_move(&item, &nufork, false);
there = curtree.root;
addpreorder(curtree.root, item, nufork, true);
promlk_add(there, item, nufork, false);
}
if (progress) {
if ( j % (( nonodes / 72 ) + 1 ) == 0 )
putchar('.');
fflush(stdout);
}
}
if (progress)
putchar('\n');
} while (bestlike < gotlike);
}
}
if (njumble > 1 && lastsp) {
for (i = 0; i < spp; i++ )
promlk_re_move(&curtree.nodep[i], &dummy, false);
if (jumb == 1 || bestree2.likelihood < bestree.likelihood)
prot_copy_(&bestree, &bestree2, nonodes, grcategs);
}
if (jumb == njumble) {
if (njumble > 1)
prot_copy_(&bestree2, &curtree, nonodes, grcategs);
else
prot_copy_(&bestree, &curtree, nonodes, grcategs);
fprintf(outfile, "\n\n");
treevaluate();
curtree.likelihood = prot_evaluate(curtree.root);
if (treeprint)
mlk_printree(outfile, &curtree);
summarize();
if (trout) {
col = 0;
promlk_treeout(curtree.root);
}
}
}
else{
if(numtrees > MAXSHIMOTREES)
shimotrees = MAXSHIMOTREES;
else
shimotrees = numtrees;
if (numtrees > 2)
emboss_initseed(inseed, &inseed0, seed);
l0gl = (double *)Malloc(shimotrees * sizeof(double));
l0gf = (double **)Malloc(shimotrees * sizeof(double *));
for (i=0; i < shimotrees; ++i)
l0gf[i] = (double *)Malloc(endsite * sizeof(double));
if (treeprint) {
fprintf(outfile, "User-defined tree");
if (numtrees > 1)
putc('s', outfile);
fprintf(outfile, ":\n\n");
}
fprintf(outfile, "\n\n");
which = 1;
max_nonodes = nonodes;
while (which <= numtrees) {
/* These initializations required each time through the loop
since multiple trees require re-initialization */
dummy_haslengths = true;
nextnode = 0;
dummy_first = true;
goteof = false;
lngths = lengthsopt;
nonodes = max_nonodes;
treestr = ajStrGetuniquePtr(&phylotrees[which-1]->Tree);
treeread(&treestr, &root, dummy_treenode, &goteof, &dummy_first,
curtree.nodep, &nextnode,
&dummy_haslengths, &grbg, initpromlnode, false, nonodes);
nonodes = nextnode;
root = curtree.nodep[root->index - 1];
curtree.root = root;
if (lngths)
tymetrav(curtree.root, &x);
if (goteof && (which <= numtrees)) {
/* if we hit the end of the file prematurely */
fprintf (outfile, "\n");
fprintf (outfile, "ERROR: trees missing at end of file.\n");
fprintf (outfile, "\tExpected number of trees:\t\t%ld\n", numtrees);
fprintf (outfile, "\tNumber of trees actually in file:\t%ld.\n\n", which - 1);
embExitBad();
}
curtree.start = curtree.nodep[0]->back;
treevaluate();
if (treeprint)
mlk_printree(outfile, &curtree);
summarize();
if (trout) {
col = 0;
promlk_treeout(curtree.root);
}
if(which < numtrees){
prot_freex_notip(nonodes, curtree.nodep);
gdispose(curtree.root, &grbg, curtree.nodep);
}
which++;
}
FClose(intree);
if (!auto_ && numtrees > 1 && weightsum > 1 )
standev2(numtrees, maxwhich, 0, endsite, maxlogl, l0gl, l0gf,
aliasweight, seed);
}
if (usertree) {
free(l0gl);
for (i=0; i < shimotrees; i++)
free(l0gf[i]);
free(l0gf);
}
prot_freetable();
if (jumb < njumble)
return;
free(contribution);
free(mp);
free_all_protx(nonodes2, curtree.nodep);
if (!usertree) {
free_all_protx(nonodes2, bestree.nodep);
if (njumble > 1)
free_all_protx(nonodes2, bestree2.nodep);
}
if (progress) {
printf("\nOutput written to file \"%s\"\n", outfilename);
if (trout)
printf("\nTree also written onto file \"%s\"\n", outtreename);
}
free(root);
} /* maketree */
void clean_up()
{
/* Free and/or close stuff */
long i;
free (rrate);
free (probcat);
free (rate);
/* Seems to require freeing every time... */
for (i = 0; i < spp; i++) {
free (y[i]);
}
free (y);
free (nayme);
free (enterorder);
free (category);
free (weight);
free (alias);
free (ally);
free (location);
free (aliasweight);
free (probmat);
free (eigmat);
/* FIXME jumble should never be enabled with usertree
*
* also -- freetree2 was making memory leak. Since that's
* broken and we're currently not bothering to free our
* other trees, it makes more sense to me to not free
* bestree2. We should fix all of them properly. Doing
* that will require a freetree variant that specifically
* handles nodes made with prot_allocx
if (!usertree && njumble > 1)
freetree2(bestree2.nodep, nonodes2);
*/
FClose(infile);
FClose(outfile);
FClose(outtree);
#ifdef MAC
fixmacfile(outfilename);
fixmacfile(outtreename);
#endif
} /* clean_up */
int main(int argc, Char *argv[])
{ /* Protein Maximum Likelihood with molecular clock */
/* Initialize mlclock.c */
mlclock_init(&curtree, &prot_evaluate);
#ifdef MAC
argc = 1; /* macsetup("Promlk", ""); */
argv[0] = "Promlk";
#endif
init(argc,argv);
emboss_getoptions("fpromlk", argc, argv);
progname = argv[0];
ibmpc = IBMCRT;
ansi = ANSICRT;
firstset = true;
doinit();
/* Data set loop */
for ( ith = 1; ith <= datasets; ith++ ) {
if ( datasets > 1 ) {
fprintf(outfile, "Data set # %ld:\n\n", ith);
if ( progress )
printf("\nData set # %ld:\n", ith);
}
getinput();
if ( ith == 1 )
firstset = false;
/* Jumble loop */
if (usertree) {
max_num_sibs = 0;
maketree();
} else
for ( jumb = 1; jumb <= njumble; jumb++ ) {
max_num_sibs = 0;
maketree();
}
}
clean_up();
printf("\nDone.\n\n");
#ifdef WIN32
phyRestoreConsoleAttributes();
#endif
embExit();
return 0;
} /* Protein Maximum Likelihood with molecular clock */
PHYLIPNEW-3.69.650/src/dnacomp.c 0000664 0001750 0001750 00000071320 11305225544 012646 0000000 0000000
#include "phylip.h"
#include "seq.h"
/* version 3.6. (c) Copyright 1993-2004 by the University of Washington.
Written by Joseph Felsenstein, Akiko Fuseki, Sean Lamont, and Andrew Keeffe.
Permission is granted to copy and use this program provided no fee is
charged for it and provided that this copyright notice is not removed. */
#define maxtrees 100 /* maximum number of tied trees stored */
AjPSeqset* seqsets = NULL;
AjPPhyloProp phyloweights = NULL;
AjPPhyloTree* phylotrees;
ajint numseqs;
ajint numwts;
typedef boolean *boolptr;
#ifndef OLDC
/* function prototypes */
void emboss_getoptions(char *pgm, int argc, char *argv[]);
//void getoptions(void);
void allocrest(void);
void deallocrest(void);
void doinit(void);
void initdnacompnode(node **, node **, node *, long, long, long *,
long *, initops, pointarray, pointarray, Char *, Char *, char **);
void makeweights(void);
void doinput(void);
void mincomp(long );
void evaluate(node *);
void localsavetree(void);
void tryadd(node *, node *, node *);
void addpreorder(node *, node *, node *);
void tryrearr(node *, boolean *);
void repreorder(node *, boolean *);
void rearrange(node **);
void describe(void);
void initboolnames(node *, boolean *);
void maketree(void);
void freerest(void);
void standev3(long, long, long, double, double *, long **, longer);
void reallocchars(void);
/* function prototypes */
#endif
extern sequence y;
Char infilename[FNMLNGTH], weightfilename[FNMLNGTH];
const char* outfilename;
const char* outtreename;
AjPFile embossoutfile;
AjPFile embossouttree;
node *root, *p;
long chars, col, ith, njumble, jumb, msets, numtrees;
long inseed, inseed0;
boolean jumble, usertree, trout, weights,
progress, stepbox, ancseq, firstset, mulsets, justwts;
steptr oldweight, necsteps;
pointarray treenode; /* pointers to all nodes in tree */
long *enterorder;
Char basechar[32]="ACMGRSVTWYHKDBNO???????????????";
bestelm *bestrees;
boolean dummy;
longer seed;
gbases *garbage;
Char ch;
Char progname[20];
long *zeros;
/* Local variables for maketree, propagated globally for C version: */
long maxwhich;
double like, maxsteps, bestyet, bestlike, bstlike2;
boolean lastrearr, recompute;
double nsteps[maxuser];
long **fsteps;
node *there;
long *place;
boolptr in_tree;
baseptr nothing;
node *temp, *temp1;
node *grbg;
void emboss_getoptions(char *pgm, int argc, char *argv[])
{
jumble = false;
njumble = 1;
outgrno = 1;
outgropt = false;
trout = true;
usertree = false;
weights = false;
justwts = false;
printdata = false;
progress = true;
treeprint = true;
stepbox = false;
ancseq = false;
numtrees = 0;
numwts = 0;
mulsets = false;
msets = 1;
embInitPV(pgm, argc, argv, "PHYLIPNEW",VERSION);
seqsets = ajAcdGetSeqsetall("sequence");
phylotrees = ajAcdGetTree("intreefile");
if (phylotrees)
{
while (phylotrees[numtrees])
numtrees++;
usertree = true;
}
phyloweights = ajAcdGetProperties("weights");
if (phyloweights)
{
weights = true;
numwts = ajPhyloPropGetSize(phyloweights);
printf("numwts: %d\n", numwts);
}
if (numseqs > 1) {
mulsets = true;
msets = numseqs;
}
else if (numwts > 1) {
mulsets = true;
msets = numwts;
justwts = true;
}
outgrno = ajAcdGetInt("outgrno");
if(outgrno != 0) outgropt = true;
else outgrno = 1;
printdata = ajAcdGetBoolean("printdata");
progress = ajAcdGetBoolean("progress");
treeprint = ajAcdGetBoolean("treeprint");
trout = ajAcdGetToggle("trout");
stepbox = ajAcdGetBoolean("stepbox");
ancseq = ajAcdGetBoolean("ancseq");
if(!usertree) {
njumble = ajAcdGetInt("njumble");
if(njumble >0) {
inseed = ajAcdGetInt("seed");
jumble = true;
emboss_initseed(inseed, &inseed0, seed);
}
else njumble = 1;
}
if((mulsets) && (!jumble)) {
jumble = true;
inseed = ajAcdGetInt("seed");
emboss_initseed(inseed, &inseed0, seed);
}
embossoutfile = ajAcdGetOutfile("outfile");
emboss_openfile(embossoutfile, &outfile, &outfilename);
if(trout) {
embossouttree = ajAcdGetOutfile("outtreefile");
emboss_openfile(embossouttree, &outtree, &outtreename);
}
fprintf(outfile, "\nDNA compatibility algorithm, version %s\n\n",VERSION);
} /* emboss_getoptions */
void reallocchars(void)
{/* The amount of chars can change between runs
this function reallocates all the variables
whose size depends on the amount of chars */
long i;
for (i = 0; i < spp; i++) {
free(y[i]);
y[i] = (Char *)Malloc(chars*sizeof(Char));
}
free(weight);
free(oldweight);
free(enterorder);
free(necsteps);
free(alias);
free(ally);
free(location);
free(in_tree);
weight = (steptr)Malloc(chars*sizeof(long));
oldweight = (steptr)Malloc(chars*sizeof(long));
enterorder = (long *)Malloc(spp*sizeof(long));
necsteps = (steptr)Malloc(chars*sizeof(long));
alias = (steptr)Malloc(chars*sizeof(long));
ally = (steptr)Malloc(chars*sizeof(long));
location = (steptr)Malloc(chars*sizeof(long));
in_tree = (boolptr)Malloc(chars*sizeof(boolean));
}
void allocrest()
{
long i;
y = (Char **)Malloc(spp*sizeof(Char *));
for (i = 0; i < spp; i++)
y[i] = (Char *)Malloc(chars*sizeof(Char));
bestrees = (bestelm *) Malloc(maxtrees*sizeof(bestelm));
for (i = 1; i <= maxtrees; i++)
bestrees[i - 1].btree = (long *)Malloc(nonodes*sizeof(long));
nayme = (naym *)Malloc(spp*sizeof(naym));
weight = (steptr)Malloc(chars*sizeof(long));
oldweight = (steptr)Malloc(chars*sizeof(long));
enterorder = (long *)Malloc(spp*sizeof(long));
necsteps = (steptr)Malloc(chars*sizeof(long));
alias = (steptr)Malloc(chars*sizeof(long));
ally = (steptr)Malloc(chars*sizeof(long));
location = (steptr)Malloc(chars*sizeof(long));
place = (long *)Malloc((2*spp-1)*sizeof(long));
in_tree = (boolptr)Malloc(spp*sizeof(boolean));
} /* allocrest */
void deallocrest()
{
long i;
for (i = 0; i < spp; i++)
free(y[i]);
free(y);
for (i = 0; i < maxtrees; i++)
free(bestrees[i].btree);
free(bestrees);
free(nayme);
free(weight);
free(oldweight);
free(enterorder);
free(necsteps);
free(alias);
free(ally);
free(location);
free(place);
free(in_tree);
} /* allocrest */
void doinit()
{
/* initializes variables */
inputnumbersseq(seqsets[0], &spp, &chars, &nonodes, 1);
if (printdata)
fprintf(outfile, "%2ld species, %3ld sites\n", spp, chars);
alloctree(&treenode, nonodes, usertree);
allocrest();
} /* doinit */
void initdnacompnode(node **p, node **grbg, node *q, long len, long nodei,
long *ntips, long *parens, initops whichinit,
pointarray treenode, pointarray nodep, Char *str, Char *ch,
char** treestr)
{
/* initializes a node */
boolean minusread;
double valyew, divisor;
switch (whichinit) {
case bottom:
gnutreenode(grbg, p, nodei, endsite, zeros);
treenode[nodei - 1] = *p;
break;
case nonbottom:
gnutreenode(grbg, p, nodei, endsite, zeros);
break;
case tip:
match_names_to_data (str, treenode, p, spp);
break;
case length:
processlength(&valyew, &divisor, ch, &minusread, treestr, parens);
/* process and discard lengths */
default:
break;
}
} /* initdnacompnode */
void makeweights()
{
/* make up weights vector to avoid duplicate computations */
long i;
for (i = 1; i <= chars; i++) {
alias[i - 1] = i;
oldweight[i - 1] = weight[i - 1];
ally[i - 1] = i;
}
sitesort(chars, weight);
sitecombine(chars);
sitescrunch(chars);
endsite = 0;
for (i = 1; i <= chars; i++) {
if (ally[i - 1] == i)
endsite++;
}
for (i = 1; i <= endsite; i++)
location[alias[i - 1] - 1] = i;
zeros = (long *)Malloc(endsite*sizeof(long));
for (i = 0; i < endsite; i++)
zeros[i] = 0;
} /* makeweights */
void doinput()
{
/* reads the input data */
long i;
if (justwts) {
if (firstset)
seq_inputdata(seqsets[ith-1], chars);
for (i = 0; i < chars; i++)
weight[i] = 1;
inputweightsstr(phyloweights->Str[ith-1], chars, weight, &weights);
if (justwts) {
fprintf(outfile, "\n\nWeights set # %ld:\n\n", ith);
if (progress)
printf("\nWeights set # %ld:\n\n", ith);
}
if (printdata)
printweights(outfile, 0, chars, weight, "Sites");
} else {
if (!firstset){
samenumspseq(seqsets[ith-1], &chars, ith);
reallocchars();
}
seq_inputdata(seqsets[ith-1], chars);
for (i = 0; i < chars; i++)
weight[i] = 1;
if (weights) {
inputweightsstr(phyloweights->Str[0], chars, weight, &weights);
if (printdata)
printweights(outfile, 0, chars, weight, "Sites");
}
}
makeweights();
makevalues(treenode, zeros, usertree);
allocnode(&temp, zeros, endsite);
allocnode(&temp1, zeros, endsite);
} /* doinput */
void mincomp(long n)
{
/* computes for each site the minimum number of steps
necessary to accomodate those species already
in the analysis, adding in species n */
long i, j, k, l, m;
bases b;
long s;
boolean allowable, deleted;
in_tree[n - 1] = true;
for (i = 0; i < endsite; i++)
necsteps[i] = 3;
for (m = 0; m <= 31; m++) {
s = 0;
l = -1;
k = m;
for (b = A; (long)b <= (long)O; b = (bases)((long)b + 1)) {
if ((k & 1) == 1) {
s |= 1L << ((long)b);
l++;
}
k /= 2;
}
for (j = 0; j < endsite; j++) {
allowable = true;
i = 1;
while (allowable && i <= spp) {
if (in_tree[i - 1] && treenode[i - 1]->base[j] != 0) {
if ((treenode[i - 1]->base[j] & s) == 0)
allowable = false;
}
i++;
}
if (allowable) {
if (l < necsteps[j])
necsteps[j] = l;
}
}
}
for (j = 0; j < endsite; j++) {
deleted = false;
for (i = 0; i < spp; i++) {
if (in_tree[i] && treenode[i]->base[j] == 0)
deleted = true;
}
if (deleted)
necsteps[j]++;
}
for (i = 0; i < endsite; i++)
necsteps[i] *= weight[i];
} /* mincomp */
void evaluate(node *r)
{
/* determines the number of steps needed for a tree. this is
the minimum number of steps needed to evolve sequences on
this tree */
long i, term;
double sum;
sum = 0.0;
for (i = 0; i < endsite; i++) {
if (r->numsteps[i] == necsteps[i])
term = weight[i];
else
term = 0;
sum += term;
if (usertree && which <= maxuser)
fsteps[which - 1][i] = term;
}
if (usertree && which <= maxuser) {
nsteps[which - 1] = sum;
if (which == 1) {
maxwhich = 1;
maxsteps = sum;
} else if (sum > maxsteps) {
maxwhich = which;
maxsteps = sum;
}
}
like = sum;
} /* evaluate */
void localsavetree()
{
/* record in place where each species has to be
added to reconstruct this tree */
long i, j;
node *p;
boolean done;
reroot(treenode[outgrno - 1], root);
savetraverse(root);
for (i = 0; i < nonodes; i++)
place[i] = 0;
place[root->index - 1] = 1;
for (i = 1; i <= spp; i++) {
p = treenode[i - 1];
while (place[p->index - 1] == 0) {
place[p->index - 1] = i;
while (!p->bottom)
p = p->next;
p = p->back;
}
if (i > 1) {
place[i - 1] = place[p->index - 1];
j = place[p->index - 1];
done = false;
while (!done) {
place[p->index - 1] = spp + i - 1;
while (!p->bottom)
p = p->next;
p = p->back;
done = (p == NULL);
if (!done)
done = (place[p->index - 1] != j);
}
}
}
} /* localsavetree */
void tryadd(node *p, node *item, node *nufork)
{
/* temporarily adds one fork and one tip to the tree.
if the location where they are added yields greater
"likelihood" than other locations tested up to that
time, then keeps that location as there */
long pos;
boolean found;
node *rute, *q;
if (p == root)
fillin(temp, item, p);
else {
fillin(temp1, item, p);
fillin(temp, temp1, p->back);
}
evaluate(temp);
if (lastrearr) {
if (like < bestlike) {
if (item == nufork->next->next->back) {
q = nufork->next;
nufork->next = nufork->next->next;
nufork->next->next = q;
q->next = nufork;
}
} else if (like >= bstlike2) {
recompute = false;
add(p, item, nufork, &root, recompute, treenode, &grbg, zeros);
rute = root->next->back;
localsavetree();
reroot(rute, root);
if (like > bstlike2) {
bestlike = bstlike2 = like;
pos = 1;
nextree = 1;
addtree(pos, &nextree, dummy, place, bestrees);
} else {
pos = 0;
findtree(&found, &pos, nextree, place, bestrees);
if (!found) {
if (nextree <= maxtrees)
addtree(pos, &nextree, dummy, place, bestrees);
}
}
re_move(item, &nufork, &root, recompute, treenode, &grbg, zeros);
recompute = true;
}
}
if (like > bestyet) {
bestyet = like;
there = p;
}
} /* tryadd */
void addpreorder(node *p, node *item, node *nufork)
{
/* traverses a binary tree, calling PROCEDURE tryadd
at a node before calling tryadd at its descendants */
if (p == NULL)
return;
tryadd(p, item, nufork);
if (!p->tip) {
addpreorder(p->next->back, item, nufork);
addpreorder(p->next->next->back, item, nufork);
}
} /* addpreorder */
void tryrearr(node *p, boolean *success)
{
/* evaluates one rearrangement of the tree.
if the new tree has greater "likelihood" than the old
one sets success := TRUE and keeps the new tree.
otherwise, restores the old tree */
node *frombelow, *whereto, *forknode, *q;
double oldlike;
if (p->back == NULL)
return;
forknode = treenode[p->back->index - 1];
if (forknode->back == NULL)
return;
oldlike = bestyet;
if (p->back->next->next == forknode)
frombelow = forknode->next->next->back;
else
frombelow = forknode->next->back;
whereto = treenode[forknode->back->index - 1];
if (whereto->next->back == forknode)
q = whereto->next->next->back;
else
q = whereto->next->back;
fillin(temp1, frombelow, q);
fillin(temp, temp1, p);
fillin(temp1, temp, whereto->back);
evaluate(temp1);
if (like <= oldlike + LIKE_EPSILON) {
if (p != forknode->next->next->back)
return;
q = forknode->next;
forknode->next = forknode->next->next;
forknode->next->next = q;
q->next = forknode;
return;
}
recompute = false;
re_move(p, &forknode, &root, recompute, treenode, &grbg, zeros);
fillin(whereto, whereto->next->back, whereto->next->next->back);
recompute = true;
add(whereto, p, forknode, &root, recompute, treenode, &grbg, zeros);
*success = true;
bestyet = like;
} /* tryrearr */
void repreorder(node *p, boolean *success)
{
/* traverses a binary tree, calling PROCEDURE tryrearr
at a node before calling tryrearr at its descendants */
if (p == NULL)
return;
tryrearr(p,success);
if (!p->tip) {
repreorder(p->next->back,success);
repreorder(p->next->next->back,success);
}
} /* repreorder */
void rearrange(node **r)
{
/* traverses the tree (preorder), finding any local
rearrangement which decreases the number of steps.
if traversal succeeds in increasing the tree's
"likelihood", PROCEDURE rearrange runs traversal again */
boolean success=true;
while (success) {
success = false;
repreorder(*r,&success);
}
} /* rearrange */
void describe()
{
/* prints ancestors, steps and table of numbers of steps in
each site and table of compatibilities */
long i, j, k;
if (treeprint) {
fprintf(outfile, "\ntotal number of compatible sites is ");
fprintf(outfile, "%10.1f\n", like);
}
if (stepbox) {
writesteps(chars, weights, oldweight, root);
fprintf(outfile,
"\n compatibility (Y or N) of each site with this tree:\n\n");
fprintf(outfile, " ");
for (i = 0; i <= 9; i++)
fprintf(outfile, "%ld", i);
fprintf(outfile, "\n *----------\n");
for (i = 0; i <= (chars / 10); i++) {
putc(' ', outfile);
fprintf(outfile, "%3ld !", i * 10);
for (j = 0; j <= 9; j++) {
k = i * 10 + j;
if (k > 0 && k <= chars) {
if (root->numsteps[location[ally[k - 1] - 1] - 1] ==
necsteps[location[ally[k - 1] - 1] - 1]) {
if (oldweight[k - 1] > 0)
putc('Y', outfile);
else
putc('y', outfile);
} else {
if (oldweight[k - 1] > 0)
putc('N', outfile);
else
putc('n', outfile);
}
} else
putc(' ', outfile);
}
putc('\n', outfile);
}
}
if (ancseq) {
hypstates(chars, root, treenode, &garbage, basechar);
putc('\n', outfile);
}
putc('\n', outfile);
if (trout) {
col = 0;
treeout(root, nextree, &col, root);
}
} /* describe */
void initboolnames(node *p, boolean *names)
{
/* sets BOOLEANs that indicate tips */
node *q;
if (p->tip) {
names[p->index - 1] = true;
return;
}
q = p->next;
while (q != p) {
initboolnames(q->back, names);
q = q->next;
}
} /* initboolnames */
void standev3(long chars, long numtrees, long maxwhich, double maxsteps,
double *nsteps, long **fsteps, longer seed)
{ /* compute and write standard deviation of user trees */
long i, j, k;
double wt, sumw, sum, sum2, sd;
double temp;
double **covar, *P, *f;
#define SAMPLES 1000
/* ????? if numtrees too big for Shimo, truncate */
if (numtrees == 2) {
fprintf(outfile, "Kishino-Hasegawa-Templeton test\n\n");
fprintf(outfile, "Tree Compatible Difference Its S.D.");
fprintf(outfile, " Significantly worse?\n\n");
which = 1;
while (which <= numtrees) {
fprintf(outfile, "%3ld %11.1f", which, nsteps[which - 1]);
if (maxwhich == which)
fprintf(outfile, " <------ best\n");
else {
sumw = 0.0;
sum = 0.0;
sum2 = 0.0;
for (i = 0; i < chars; i++) {
if (weight[i] > 0) {
wt = weight[i];
sumw += wt;
temp = (fsteps[which - 1][i] - fsteps[maxwhich - 1][i]);
sum += temp;
sum2 += temp * temp / wt;
}
}
temp = sum / sumw;
sd = sqrt(sumw / (sumw - 1.0) * (sum2 - temp * temp));
fprintf(outfile, " %10.1f %11.4f",
(maxsteps-nsteps[which - 1]), sd);
if (sum > 1.95996 * sd)
fprintf(outfile, " Yes\n");
else
fprintf(outfile, " No\n");
}
which++;
}
fprintf(outfile, "\n\n");
} else { /* Shimodaira-Hasegawa test using normal approximation */
fprintf(outfile, "Shimodaira-Hasegawa test\n\n");
covar = (double **)Malloc(numtrees*sizeof(double *));
sumw = 0.0;
for (i = 0; i < chars; i++)
sumw += weight[i];
for (i = 0; i < numtrees; i++)
covar[i] = (double *)Malloc(numtrees*sizeof(double));
for (i = 0; i < numtrees; i++) { /* compute covariances of trees */
sum = nsteps[i]/sumw;
for (j = 0; j <=i; j++) {
sum2 = nsteps[j]/sumw;
temp = 0.0;
for (k = 0; k < chars; k++) {
if (weight[k] > 0) {
wt = weight[k];
temp = temp + wt*(fsteps[i][k]/wt-sum)
*(fsteps[j][k]/wt-sum2);
}
}
covar[i][j] = temp;
if (i != j)
covar[j][i] = temp;
}
}
for (i = 0; i < numtrees; i++) { /* in-place Cholesky decomposition
of trees x trees covariance matrix */
sum = 0.0;
for (j = 0; j <= i-1; j++)
sum = sum + covar[i][j] * covar[i][j];
temp = sqrt(covar[i][i] - sum);
covar[i][i] = temp;
for (j = i+1; j < numtrees; j++) {
sum = 0.0;
for (k = 0; k < i; k++)
sum = sum + covar[i][k] * covar[j][k];
if (fabs(temp) < 1.0E-12)
covar[j][i] = 0.0;
else
covar[j][i] = (covar[j][i] - sum)/temp;
}
}
f = (double *)Malloc(numtrees*sizeof(double)); /* vector of P's of trees */
P = (double *)Malloc(numtrees*sizeof(double)); /* vector of P's of trees */
for (i = 0; i < numtrees; i++)
P[i] = 0.0;
sum2 = nsteps[0]; /* sum2 will be largest # of compat. sites */
for (i = 1; i < numtrees; i++)
if (sum2 < nsteps[i])
sum2 = nsteps[i];
for (i = 1; i < SAMPLES; i++) { /* loop over resampled trees */
for (j = 0; j < numtrees; j++) { /* draw vectors */
sum = 0.0;
for (k = 0; k <= j; k++)
sum += normrand(seed)*covar[j][k];
f[j] = sum;
}
sum = f[1];
for (j = 1; j < numtrees; j++) /* get max of vector */
if (f[j] > sum)
sum = f[j];
for (j = 0; j < numtrees; j++) /* accumulate P's */
if (sum2-nsteps[j] <= sum-f[j])
P[j] += 1.0/SAMPLES;
}
fprintf(outfile, "Tree Compatible Difference P value");
fprintf(outfile, " Significantly worse?\n\n");
for (i = 0; i < numtrees; i++) {
fprintf(outfile, "%3ld %10.1f", i+1, nsteps[i]);
if ((maxwhich-1) == i)
fprintf(outfile, " <------ best\n");
else {
fprintf(outfile, " %10.1f %10.3f", sum2-nsteps[i], P[i]);
if (P[i] < 0.05)
fprintf(outfile, " Yes\n");
else
fprintf(outfile, " No\n");
}
}
fprintf(outfile, "\n");
free(P); /* free the variables we Malloc'ed */
free(f);
for (i = 0; i < numtrees; i++)
free(covar[i]);
free(covar);
}
} /* standev */
void maketree()
{
/* constructs a binary tree from the pointers in treenode.
adds each node at location which yields highest "likelihood"
then rearranges the tree for greatest "likelihood" */
long i, j, nextnode;
boolean firsttree, goteof, haslengths;
double gotlike;
node *item, *nufork, *dummy;
pointarray nodep;
boolean *names;
char* treestr;
if (!usertree) {
recompute = true;
for (i = 0; i < spp; i++)
in_tree[i] = false;
for (i = 1; i <= spp; i++)
enterorder[i - 1] = i;
if (jumble)
randumize(seed, enterorder);
root = treenode[enterorder[0] - 1];
add(treenode[enterorder[0] - 1], treenode[enterorder[1] - 1],
treenode[spp], &root, recompute, treenode, &grbg, zeros);
if (progress) {
printf("Adding species:\n");
writename(0, 2, enterorder);
#ifdef WIN32
phyFillScreenColor();
#endif
}
in_tree[0] = true;
in_tree[1] = true;
lastrearr = false;
for (i = 3; i <= spp; i++) {
mincomp(i);
bestyet = -350.0 * spp * chars;
item = treenode[enterorder[i - 1] - 1];
nufork = treenode[spp + i - 2];
there = root;
addpreorder(root, item, nufork);
add(there, item, nufork, &root, recompute, treenode, &grbg, zeros);
like = bestyet;
rearrange(&root);
if (progress) {
writename(i - 1, 1, enterorder);
#ifdef WIN32
phyFillScreenColor();
#endif
}
lastrearr = (i == spp);
if (lastrearr) {
if (progress) {
printf("\nDoing global rearrangements\n");
printf(" !");
for (j = 1; j <= nonodes; j++)
if ( j % (( nonodes / 72 ) + 1 ) == 0 )
putchar('-');
printf("!\n");
#ifdef WIN32
phyFillScreenColor();
#endif
}
bestlike = bestyet;
if (jumb == 1) {
bstlike2 = bestlike;
nextree = 1;
}
do {
if (progress)
printf(" ");
gotlike = bestlike;
for (j = 0; j < nonodes; j++) {
bestyet = -10.0 * spp * chars;
item = treenode[j];
there = root;
if (item != root) {
re_move(item, &nufork, &root, recompute, treenode, &grbg, zeros);
there = root;
addpreorder(root, item, nufork);
add(there, item, nufork, &root, recompute, treenode, &grbg, zeros);
}
if (progress) {
if ( j % (( nonodes / 72 ) + 1 ) == 0 )
putchar('.');
fflush(stdout);
}
}
if (progress)
putchar('\n');
} while (bestlike > gotlike);
}
}
if (progress)
putchar('\n');
for (i = spp - 1; i >= 1; i--)
re_move(treenode[i], &dummy, &root, recompute, treenode, &grbg, zeros);
if (jumb == njumble) {
if (treeprint) {
putc('\n', outfile);
if (nextree == 2)
fprintf(outfile, "One most parsimonious tree found:\n");
else
fprintf(outfile, "%6ld trees in all found\n", nextree - 1);
}
if (nextree > maxtrees + 1) {
if (treeprint)
fprintf(outfile, "here are the first%4ld of them\n", (long)maxtrees);
nextree = maxtrees + 1;
}
if (treeprint)
putc('\n', outfile);
recompute = false;
for (i = 0; i <= (nextree - 2); i++) {
root = treenode[0];
add(treenode[0], treenode[1], treenode[spp], &root, recompute,
treenode, &grbg, zeros);
for (j = 3; j <= spp; j++)
add(treenode[bestrees[i].btree[j - 1] - 1], treenode[j - 1],
treenode[spp + j - 2], &root, recompute, treenode, &grbg, zeros);
reroot(treenode[outgrno - 1], root);
postorder(root);
evaluate(root);
printree(root, 1.0);
describe();
for (j = 1; j < spp; j++)
re_move(treenode[j], &dummy, &root, recompute, treenode, &grbg, zeros);
}
}
}
else {
if (numtrees > 2)
emboss_initseed(inseed, &inseed0, seed);
if (treeprint) {
fprintf(outfile, "User-defined tree");
if (numtrees > 1)
putc('s', outfile);
fprintf(outfile, ":\n");
}
fsteps = (long **)Malloc(maxuser*sizeof(long *));
for (j = 1; j <= maxuser; j++)
fsteps[j - 1] = (long *)Malloc(endsite*sizeof(long));
names = (boolean *)Malloc(spp*sizeof(boolean));
nodep = NULL;
maxsteps = 0.0;
which = 1;
while (which <= numtrees) {
firsttree = true;
nextnode = 0;
haslengths = true;
treestr = ajStrGetuniquePtr(&phylotrees[which-1]->Tree);
treeread(&treestr, &root, treenode, &goteof, &firsttree,
nodep, &nextnode, &haslengths, &grbg,
initdnacompnode,false,nonodes);
for (j = 0; j < spp; j++)
names[j] = false;
initboolnames(root, names);
for (j = 0; j < spp; j++)
in_tree[j] = names[j];
j = 1;
while (!in_tree[j - 1])
j++;
mincomp(j);
ajUtilCatch();
if (outgropt)
reroot(treenode[outgrno - 1], root);
postorder(root);
evaluate(root);
printree(root, 1.0);
describe();
which++;
}
FClose(intree);
putc('\n', outfile);
if (numtrees > 1 && chars > 1 ) {
standev3(chars, numtrees, maxwhich, maxsteps, nsteps, fsteps, seed);
}
for (j = 1; j <= maxuser; j++)
free(fsteps[j - 1]);
free(fsteps);
free(names);
}
if (jumb == njumble) {
if (progress) {
printf("Output written to file \"%s\"\n", outfilename);
if (trout)
printf("\nTrees also written onto file \"%s\"\n", outtreename);
putchar('\n');
}
}
} /* maketree */
void freerest()
{
if (!usertree) {
freenode(&temp);
freenode(&temp1);
}
freegrbg(&grbg);
if (ancseq)
freegarbage(&garbage);
free(zeros);
freenodes(nonodes, treenode);
} /* freerest */
int main(int argc, Char *argv[])
{ /* DNA compatibility by uphill search */
/* reads in spp, chars, and the data. Then calls maketree to
construct the tree */
#ifdef MAC
argc = 1; /* macsetup("Dnacomp",""); */
argv[0]="Dnacomp";
#endif
init(argc, argv);
emboss_getoptions("fdnacomp", argc, argv);
garbage = NULL;
grbg = NULL;
ibmpc = IBMCRT;
ansi = ANSICRT;
firstset = true;
doinit();
for (ith = 1; ith <= msets; ith++) {
doinput();
if (ith == 1)
firstset = false;
if (msets > 1 && !justwts) {
fprintf(outfile, "Data set # %ld:\n\n", ith);
if (progress)
printf("Data set # %ld:\n\n", ith);
}
for (jumb = 1; jumb <= njumble; jumb++)
maketree();
freerest();
}
freetree(nonodes, treenode);
FClose(infile);
FClose(outfile);
FClose(outtree);
#ifdef MAC
fixmacfile(outfilename);
fixmacfile(outtreename);
#endif
#ifdef WIN32
phyRestoreConsoleAttributes();
#endif
ajSeqsetDelarray(&seqsets);
ajPhyloPropDel(&phyloweights);
ajPhyloTreeDelarray(&phylotrees);
ajFileClose(&embossoutfile);
ajFileClose(&embossouttree);
deallocrest();
embExit();
return 0;
} /* DNA compatibility by uphill search */
PHYLIPNEW-3.69.650/src/moves.c 0000664 0001750 0001750 00000013752 10775447511 012375 0000000 0000000
#include "phylip.h"
#include "moves.h"
void inpnum(long *n, boolean *success)
{
/* used by dnamove, dolmove, move, & retree */
int fields;
char line[100];
#ifdef WIN32
phyFillScreenColor();
#endif
fflush(stdout);
getstryng(line);
*n = atof(line);
fields = sscanf(line,"%ld",n);
*success = (fields == 1);
} /* inpnum */
void prereverse(boolean ansi)
{
/* turn on reverse video */
printf(ansi ? "\033[7m": "");
} /* prereverse */
void postreverse(boolean ansi)
{
/* turn off reverse video */
printf(ansi ? "\033[0m" : "");
} /* postreverse */
void chwrite(Char ch, long num, long *pos, long leftedge, long screenwidth)
{
long i;
for (i = 1; i <= num; i++) {
if ((*pos) >= leftedge && (*pos) - leftedge + 1 < screenwidth)
putchar(ch);
(*pos)++;
}
} /* chwrite */
void nnwrite(long nodenum,long num,long *pos,long leftedge,long screenwidth)
{
long i, leftx;
leftx = leftedge - (*pos);
if ((*pos) >= leftedge && (*pos) - leftedge + num < screenwidth)
printf("%*ld", (int)num, nodenum);
else if (leftx > 0 && leftx < 3)
for(i=0;i= leftedge && (*pos) - leftedge + 1 < screenwidth)
printf("%*s", (int)length, s);
(*pos) += length;
} /* stwrite */
void help(const char *letters)
{
/* display help information */
char input[100];
printf("\n\nR Rearrange a tree by moving a node or group\n");
printf("# Show the states of the next %s that doesn't fit tree\n", letters);
printf("+ Show the states of the next %s\n", letters);
printf("- ... of the previous %s\n", letters);
printf("S Show the states of a given %s\n", letters);
printf(". redisplay the same tree again\n");
printf("T Try all possible positions of a node or group\n");
printf("U Undo the most recent rearrangement\n");
printf("W Write tree to a file\n");
printf("O select an Outgroup for the tree\n");
printf("F Flip (rotate) branches at a node\n");
printf("H Move viewing window to the left\n");
printf("J Move viewing window downward\n");
printf("K Move viewing window upward\n");
printf("L Move viewing window to the right\n");
printf("C show only one Clade (subtree) (useful if tree is too big)\n");
printf("? Help (this screen)\n");
printf("Q (Quit) Exit from program\n");
printf("X Exit from program\n\n\n");
printf("TO CONTINUE, PRESS ON THE Return OR Enter KEY");
#ifdef WIN32
phyFillScreenColor();
#endif
fflush(stdout);
getstryng(input);
} /* help */
void window(adjwindow action, long *leftedge, long *topedge, long hscroll,
long vscroll, long treelines, long screenlines,
long screenwidth, long farthest, boolean subtree)
{
/* move viewing window of tree */
switch (action) {
case left:
if (*leftedge != 1)
*leftedge -= hscroll;
break;
case downn:
/* The 'topedge + 6' is needed to allow downward scrolling
when part of the tree is above the screen and only 1 or 2 lines
are below it. */
if (treelines - *topedge + 6 >= screenlines)
*topedge += vscroll;
break;
case upp:
if (*topedge != 1)
*topedge -= vscroll;
break;
case right:
if ((farthest + 6 + nmlngth + ((subtree) ? 8 : 0)) >
(*leftedge + screenwidth))
*leftedge += hscroll;
break;
}
} /* window */
void pregraph(boolean ansi)
{
/* turn on graphic characters */
/* used in move & dolmove */
printf(ansi ? "\033(0" : "");
} /* pregraph */
void pregraph2(boolean ansi)
{
/* turn on graphic characters */
/* used in dnamove & retree */
if (ansi) {
printf("\033(0");
printf("\033[10m");
}
} /* pregraph2 */
void postgraph(boolean ansi)
{
/* turn off graphic characters */
/* used in move & dolmove */
printf(ansi ? "\033(B" : "");
} /* postgraph */
void postgraph2(boolean ansi)
{
/* turn off graphic characters */
/* used in dnamove & retree */
if (ansi) {
printf("\033[11m");
printf("\033(B");
}
} /* postgraph2 */
void nextinc(long *dispchar, long *dispword, long *dispbit, long chars,
long bits, boolean *display, steptr numsteps, steptr weight)
{
/* show next incompatible character */
/* used in move & dolmove */
long disp0;
boolean done;
*display = true;
disp0 = *dispchar;
done = false;
do {
(*dispchar)++;
if (*dispchar > chars) {
*dispchar = 1;
done = (disp0 == 0);
}
} while (!(numsteps[*dispchar - 1] >
weight[*dispchar - 1] ||
*dispchar == disp0 || done));
*dispword = (*dispchar - 1) / bits + 1;
*dispbit = (*dispchar - 1) % bits + 1;
} /* nextinc */
void nextchar(long *dispchar, long *dispword, long *dispbit, long chars,
long bits, boolean *display)
{
/* show next character */
/* used in move & dolmove */
*display = true;
(*dispchar)++;
if (*dispchar > chars)
*dispchar = 1;
*dispword = (*dispchar - 1) / bits + 1;
*dispbit = (*dispchar - 1) % bits + 1;
} /* nextchar */
void prevchar(long *dispchar, long *dispword, long *dispbit, long chars,
long bits, boolean *display)
{
/* show previous character */
/* used in move & dolmove */
*display = true;
(*dispchar)--;
if (*dispchar < 1)
*dispchar = chars;
*dispword = (*dispchar - 1) / bits + 1;
*dispbit = (*dispchar - 1) % bits + 1;
} /* prevchar */
void show(long *dispchar, long *dispword, long *dispbit, long chars,
long bits, boolean *display)
{
/* used in move & dolmove */
long i;
boolean ok;
do {
printf("SHOW: (Character number or 0 to see none)? ");
inpnum(&i, &ok);
ok = (ok && (i == 0 || (i >= 1 && i <= chars)));
if (ok && i != 0) {
*display = true;
*dispchar = i;
*dispword = (i - 1) / bits + 1;
*dispbit = (i - 1) % bits + 1;
}
if (ok && i == 0)
*display = false;
} while (!ok);
} /* show */
PHYLIPNEW-3.69.650/src/move.c 0000664 0001750 0001750 00000113146 11305225544 012176 0000000 0000000
#include "phylip.h"
#include "disc.h"
#include "moves.h"
#include "wagner.h"
/* version 3.6. (c) Copyright 1993-2004 by the University of Washington.
Written by Joseph Felsenstein, Akiko Fuseki, Sean Lamont, and Andrew Keeffe.
Permission is granted to copy and use this program provided no fee is
charged for it and provided that this copyright notice is not removed. */
#define overr 4
#define which 1
AjPPhyloState* phylostates = NULL;
AjPPhyloProp phyloweights = NULL;
AjPPhyloProp phyloanc = NULL;
AjPPhyloProp phylomix = NULL;
AjPPhyloProp phylofact = NULL;
AjPPhyloTree* phylotrees = NULL;
typedef enum {
horiz, vert, up, overt, upcorner, downcorner, onne, zerro, question
} chartype;
typedef enum {
arb, use, spec
} howtree;
typedef enum {
rearr, flipp, reroott, none
} rearrtype;
#ifndef OLDC
/*function prototypes */
//void getoptions(void);
void emboss_getoptions(char *pgm, int argc, char *argv[]);
void inputoptions(void);
void allocrest(void);
void doinput(void);
void configure(void);
void prefix(chartype);
void postfix(chartype);
void makechar(chartype);
void move_fillin(node *);
void move_postorder(node *);
void evaluate(node *);
void reroot(node *);
void move_filltrav(node *);
void move_hyptrav(node *);
void move_hypstates(void);
void grwrite(chartype, long, long *);
void move_drawline(long, long);
void move_printree(void);
void arbitree(void);
void yourtree(void);
void initmovenode(node **, node **, node *, long, long, long *, long *,
initops, pointarray, pointarray, Char *, Char *, char**);
void buildtree(void);
void rearrange(void);
void tryadd(node *, node *, node *, double *);
void addpreorder(node *, node *, node *, double *);
void try(void);
void undo(void);
void treewrite(boolean);
void clade(void);
void flip(void);
void changeoutgroup(void);
void redisplay(void);
void treeconstruct(void);
/*function prototypes */
#endif
char infilename[FNMLNGTH],intreename[FNMLNGTH], weightfilename[FNMLNGTH], ancfilename[FNMLNGTH], mixfilename[FNMLNGTH], factfilename[FNMLNGTH];
const char* outtreename;
AjPFile embossouttree;
node *root;
long outgrno, screenlines, col, treelines, leftedge, topedge,
vmargin, hscroll, vscroll, scrollinc, screenwidth, farthest;
/* outgrno indicates outgroup */
boolean weights, outgropt, ancvar, questions, allsokal,
allwagner, mixture, factors, noroot, waswritten;
boolean *ancone, *anczero, *ancone0, *anczero0;
Char *factor;
pointptr treenode; /* pointers to all nodes in tree */
double threshold;
double *threshwt;
bitptr wagner, wagner0;
unsigned char che[9];
boolean reversed[9];
boolean graphic[9];
howtree how;
gbit *garbage;
char* progname;
Char ch;
/* Variables for treeread */
boolean usertree, goteof, firsttree, haslengths;
pointarray nodep;
node *grbg;
long *zeros;
/* Local variables for treeconstruct, propagated globally for C vesion: */
long dispchar, dispword, dispbit, atwhat, what, fromwhere, towhere,
oldoutgrno, compatible;
double like, bestyet, gotlike;
Char *guess;
boolean display, newtree, changed, subtree, written, oldwritten, restoring,
wasleft, oldleft, earlytree;
boolean *in_tree;
steptr numsteps, numsone, numszero;
long fullset;
bitptr steps, zeroanc, oneanc;
node *nuroot;
rearrtype lastop;
boolean *names;
void emboss_getoptions(char *pgm, int argc, char *argv[])
{
AjPStr initialtree = NULL;
AjPStr method = NULL;
how = arb;
usertree = false;
goteof = false;
outgrno = 1;
outgropt = false;
weights = false;
ancvar = false;
allsokal = false;
allwagner = true;
mixture = false;
factors = false;
screenlines = 24;
scrollinc = 20;
screenwidth = 80;
embInitPV(pgm, argc, argv, "PHYLIPNEW",VERSION);
phylostates = ajAcdGetDiscretestates("infile");
phyloweights = ajAcdGetProperties("weights");
if(phyloweights) weights = true;
outgrno = ajAcdGetInt("outgrno");
if(outgrno != 0) outgropt = true;
else outgrno = 1;
threshold = ajAcdGetFloat("threshold");
method = ajAcdGetListSingle("method");
if(ajStrMatchC(method, "w")) allwagner = true;
else if(ajStrMatchC(method, "c")) allsokal = true;
else if(ajStrMatchC(method, "m")) {
mixture = allwagner = true;
phylomix = ajAcdGetProperties("mixfile");
}
initialtree = ajAcdGetListSingle("initialtree");
if(ajStrMatchC(initialtree, "a")) how = arb;
if(ajStrMatchC(initialtree, "u")) how = use;
if(ajStrMatchC(initialtree, "s")) {
how = spec;
phylotrees = ajAcdGetTree("intreefile");
usertree = true;
}
phyloanc = ajAcdGetProperties("ancfile");
if(phyloanc) ancvar = true;
phylofact = ajAcdGetProperties("factorfile");
if(phylofact) factors = true;
screenwidth = ajAcdGetInt("screenwidth");
screenlines = ajAcdGetInt("screenlines");
if (scrollinc < screenwidth / 2.0)
hscroll = scrollinc;
else
hscroll = screenwidth / 2;
if (scrollinc < screenlines / 2.0)
vscroll = scrollinc;
else
vscroll = screenlines / 2;
embossouttree = ajAcdGetOutfile("outtreefile");
emboss_openfile(embossouttree, &outtree, &outtreename);
} /*emboss_getoptions */
void inputoptions()
{
/* input the information on the options */
long i;
for (i = 0; i < (chars); i++)
weight[i] = 1;
if (ancvar)
inputancestorsstr(phyloanc->Str[0], anczero0, ancone0);
if (factors) {
factor = (Char *)Malloc(chars*sizeof(Char));
inputfactorsstr(phylofact->Str[0], chars, factor, &factors);
}
if (mixture)
inputmixturestr(phylomix->Str[0], wagner0);
if (weights)
inputweightsstr(phyloweights->Str[0], chars, weight, &weights);
putchar('\n');
if (weights)
printweights(stdout, 0, chars, weight, "Characters");
for (i = 0; i < (words); i++) {
if (mixture)
wagner[i] = wagner0[i];
else if (allsokal)
wagner[i] = 0;
else
wagner[i] = (1L << (bits + 1)) - (1L << 1);
}
if (allsokal && !mixture)
printf("Camin-Sokal parsimony method\n\n");
if (allwagner && !mixture)
printf("Wagner parsimony method\n\n");
if (mixture)
printmixture(stdout, wagner);
for (i = 0; i < (chars); i++) {
if (!ancvar) {
anczero[i] = true;
ancone[i] = (((1L << (i % bits + 1)) & wagner[i / bits]) != 0);
} else {
anczero[i] = anczero0[i];
ancone[i] = ancone0[i];
}
}
if (factors)
printfactors(stdout, chars, factor, "");
if (ancvar)
printancestors(stdout, anczero, ancone);
noroot = true;
questions = false;
for (i = 0; i < (chars); i++) {
if (weight[i] > 0) {
noroot = (noroot && ancone[i] && anczero[i] &&
((((1L << (i % bits + 1)) & wagner[i / bits]) != 0)
|| threshold <= 2.0));
}
questions = (questions || (ancone[i] && anczero[i]));
threshwt[i] = threshold * weight[i];
}
} /* inputoptions */
void allocrest()
{
nayme = (naym *)Malloc(spp*sizeof(naym));
in_tree = (boolean *)Malloc(nonodes*sizeof(boolean));
extras = (steptr)Malloc(chars*sizeof(long));
weight = (steptr)Malloc(chars*sizeof(long));
numsteps = (steptr)Malloc(chars*sizeof(long));
numsone = (steptr)Malloc(chars*sizeof(long));
numszero = (steptr)Malloc(chars*sizeof(long));
threshwt = (double *)Malloc(chars*sizeof(double));
guess = (Char *)Malloc(chars*sizeof(Char));
ancone = (boolean *)Malloc(chars*sizeof(boolean));
anczero = (boolean *)Malloc(chars*sizeof(boolean));
ancone0 = (boolean *)Malloc(chars*sizeof(boolean));
anczero0 = (boolean *)Malloc(chars*sizeof(boolean));
wagner = (bitptr)Malloc(words*sizeof(long));
wagner0 = (bitptr)Malloc(words*sizeof(long));
steps = (bitptr)Malloc(words*sizeof(long));
zeroanc = (bitptr)Malloc(words*sizeof(long));
oneanc = (bitptr)Malloc(words*sizeof(long));
} /* allocrest */
void doinput()
{
/* reads the input data */
inputnumbersstate(phylostates[0], &spp, &chars, &nonodes, 1);
words = chars / bits + 1;
printf("%2ld species, %3ld characters\n", spp, chars);
alloctree(&treenode);
setuptree(treenode);
allocrest();
inputoptions();
disc_inputdata(phylostates[0], treenode, true, false, stdout);
} /* doinput */
void configure()
{
/* configure to machine -- set up special characters */
chartype a;
for (a = horiz; (long)a <= (long)question; a = (chartype)((long)a + 1))
reversed[(long)a] = false;
for (a = horiz; (long)a <= (long)question; a = (chartype)((long)a + 1))
graphic[(long)a] = false;
if (ibmpc) {
che[(long)horiz] = 205;
graphic[(long)horiz] = true;
che[(long)vert] = 186;
graphic[(long)vert] = true;
che[(long)up] = 186;
graphic[(long)up] = true;
che[(long)overt] = 205;
graphic[(long)overt] = true;
che[(long)onne] = 219;
reversed[(long)onne] = true;
che[(long)zerro] = 176;
graphic[(long)zerro] = true;
che[(long)question] = 178; /* or try CHR(177) */
graphic[(long)question] = true;
che[(long)upcorner] = 200;
graphic[(long)upcorner] = true;
che[(long)downcorner] = 201;
graphic[(long)downcorner] = true;
return;
}
if (ansi) {
che[(long)onne] = ' ';
reversed[(long)onne] = true;
che[(long)horiz] = che[(long)onne];
reversed[(long)horiz] = true;
che[(long)vert] = che[(long)onne];
reversed[(long)vert] = true;
che[(long)up] = 'x';
graphic[(long)up] = true;
che[(long)overt] = 'q';
graphic[(long)overt] = true;
che[(long)zerro] = 'a';
graphic[(long)zerro] = true;
reversed[(long)zerro] = true;
che[(long)question] = '?';
reversed[(long)question] = true;
che[(long)upcorner] = 'm';
graphic[(long)upcorner] = true;
che[(long)downcorner] = 'l';
graphic[(long)downcorner] = true;
return;
}
che[(long)horiz] = '=';
che[(long)vert] = ' ';
che[(long)up] = '!';
che[(long)overt] = '-';
che[(long)onne] = '*';
che[(long)zerro] = '=';
che[(long)question] = '.';
che[(long)upcorner] = '`';
che[(long)downcorner] = ',';
} /* configure */
void prefix(chartype a)
{
/* give prefix appropriate for this character */
if (reversed[(long)a])
prereverse(ansi);
if (graphic[(long)a])
pregraph(ansi);
} /* prefix */
void postfix(chartype a)
{
/* give postfix appropriate for this character */
if (reversed[(long)a])
postreverse(ansi);
if (graphic[(long)a])
postgraph(ansi);
} /* postfix */
void makechar(chartype a)
{
/* print out a character with appropriate prefix or postfix */
prefix(a);
putchar(che[(long)a]);
postfix(a);
} /* makechar */
void move_fillin(node *p)
{
/* Sets up for each node in the tree two statesets.
stateone and statezero are the sets of character
states that must be 1 or must be 0, respectively,
in a most parsimonious reconstruction, based on the
information at or above this node. Note that this
state assignment may change based on information further
down the tree. If a character is in both sets it is in
state "P". If in neither, it is "?". */
long i;
long l0, l1, r0, r1, st, wa, za, oa;
for (i = 0; i < (words); i++) {
l0 = p->next->back->statezero[i];
l1 = p->next->back->stateone[i];
r0 = p->next->next->back->statezero[i];
r1 = p->next->next->back->stateone[i];
wa = wagner[i];
za = zeroanc[i];
oa = oneanc[i];
st = (l1 & r0) | (l0 & r1);
steps[i] = st;
p->stateone[i] = (l1 | r1) & (~(st & (wa | za)));
p->statezero[i] = (l0 | r0) & (~(st & (wa | oa)));
}
} /* move_fillin */
void move_postorder(node *p)
{
/* traverses a binary tree, calling function fillin at a
node's descendants before calling fillin at the node */
if (p->tip)
return;
move_postorder(p->next->back);
move_postorder(p->next->next->back);
move_fillin(p);
count(steps, zeroanc, numszero, numsone);
} /* move_postorder */
void evaluate(node *r)
{
/* Determines the number of steps needed for a tree.
This is the minimum number needed to evolve chars on this tree */
long i, stepnum, smaller;
double sum;
boolean nextcompat, thiscompat, done;
sum = 0.0;
for (i = 0; i < (chars); i++) {
numszero[i] = 0;
numsone[i] = 0;
}
for (i = 0; i < (words); i++) {
zeroanc[i] = fullset;
oneanc[i] = 0;
}
compatible = 0;
nextcompat = true;
move_postorder(r);
count(r->stateone, zeroanc, numszero, numsone);
for (i = 0; i < (words); i++) {
zeroanc[i] = 0;
oneanc[i] = fullset;
}
move_postorder(r);
count(r->statezero, zeroanc, numszero, numsone);
for (i = 0; i < (chars); i++) {
smaller = spp * weight[i];
numsteps[i] = smaller;
if (anczero[i]) {
numsteps[i] = numszero[i];
smaller = numszero[i];
}
if (ancone[i] && numsone[i] < smaller)
numsteps[i] = numsone[i];
stepnum = numsteps[i] + extras[i];
if (stepnum <= threshwt[i])
sum += stepnum;
else
sum += threshwt[i];
thiscompat = (stepnum <= weight[i]);
if (factors) {
done = (i + 1 == chars);
if (!done)
done = (factor[i + 1] != factor[i]);
nextcompat = (nextcompat && thiscompat);
if (done) {
if (nextcompat)
compatible += weight[i];
nextcompat = true;
}
} else if (thiscompat)
compatible += weight[i];
guess[i] = '?';
if (!ancone[i] ||
(anczero[i] && numszero[i] < numsone[i]))
guess[i] = '0';
else if (!anczero[i] ||
(ancone[i] && numsone[i] < numszero[i]))
guess[i] = '1';
}
like = -sum;
} /* evaluate */
void reroot(node *outgroup)
{
/* reorients tree, putting outgroup in desired position. */
node *p, *q, *newbottom, *oldbottom;
boolean onleft;
if (outgroup->back->index == root->index)
return;
newbottom = outgroup->back;
p = treenode[newbottom->index - 1]->back;
while (p->index != root->index) {
oldbottom = treenode[p->index - 1];
treenode[p->index - 1] = p;
p = oldbottom->back;
}
onleft = (p == root->next);
if (restoring)
if (!onleft && wasleft){
p = root->next->next;
q = root->next;
} else {
p = root->next;
q = root->next->next;
}
else {
if (onleft)
oldoutgrno = root->next->next->back->index;
else
oldoutgrno = root->next->back->index;
wasleft = onleft;
p = root->next;
q = root->next->next;
}
p->back->back = q->back;
q->back->back = p->back;
p->back = outgroup;
q->back = outgroup->back;
if (restoring) {
if (!onleft && wasleft) {
outgroup->back->back = root->next;
outgroup->back = root->next->next;
} else {
outgroup->back->back = root->next->next;
outgroup->back = root->next;
}
} else {
outgroup->back->back = root->next->next;
outgroup->back = root->next;
}
treenode[newbottom->index - 1] = newbottom;
} /* reroot */
void move_filltrav(node *r)
{
/* traverse to fill in interior node states */
if (r->tip)
return;
move_filltrav(r->next->back);
move_filltrav(r->next->next->back);
move_fillin(r);
} /* move_filltrav */
void move_hyptrav(node *r)
{
/* compute states at one interior node */
long i;
boolean bottom;
long l0, l1, r0, r1, s0, s1, a0, a1, temp, wa;
gbit *zerobelow = NULL, *onebelow = NULL;
disc_gnu(&zerobelow, &garbage);
disc_gnu(&onebelow, &garbage);
bottom = (r->back == NULL);
if (bottom) {
memcpy(zerobelow->bits_, zeroanc, words*sizeof(long));
memcpy(onebelow->bits_, oneanc, words*sizeof(long));
} else {
memcpy(zerobelow->bits_, treenode[r->back->index - 1]->statezero,
words*sizeof(long));
memcpy(onebelow->bits_, treenode[r->back->index - 1]->stateone,
words*sizeof(long));
}
for (i = 0; i < (words); i++) {
s0 = r->statezero[i];
s1 = r->stateone[i];
a0 = zerobelow->bits_[i];
a1 = onebelow->bits_[i];
if (!r->tip) {
wa = wagner[i];
l0 = r->next->back->statezero[i];
l1 = r->next->back->stateone[i];
r0 = r->next->next->back->statezero[i];
r1 = r->next->next->back->stateone[i];
s0 = (wa & ((a0 & l0) | (a0 & r0) | (l0 & r0))) |
(fullset & (~wa) & s0);
s1 = (wa & ((a1 & l1) | (a1 & r1) | (l1 & r1))) |
(fullset & (~wa) & s1);
temp = fullset & (~(s0 | s1 | l1 | l0 | r1 | r0));
s0 |= temp & a0;
s1 |= temp & a1;
r->statezero[i] = s0;
r->stateone[i] = s1;
}
}
if (((1L << dispbit) & r->stateone[dispword - 1]) != 0) {
if (((1L << dispbit) & r->statezero[dispword - 1]) != 0)
r->state = '?';
else
r->state = '1';
} else {
if (((1L << dispbit) & r->statezero[dispword - 1]) != 0)
r->state = '0';
else
r->state = '?';
}
if (!r->tip) {
move_hyptrav(r->next->back);
move_hyptrav(r->next->next->back);
}
disc_chuck(zerobelow, &garbage);
disc_chuck(onebelow, &garbage);
} /* move_hyptrav */
void move_hypstates()
{
/* fill in and describe states at interior nodes */
long i, j, k;
for (i = 0; i < (words); i++) {
zeroanc[i] = 0;
oneanc[i] = 0;
}
for (i = 0; i < (chars); i++) {
j = i / bits + 1;
k = i % bits + 1;
if (guess[i] == '0')
zeroanc[j - 1] = ((long)zeroanc[j - 1]) | (1L << k);
if (guess[i] == '1')
oneanc[j - 1] = ((long)oneanc[j - 1]) | (1L << k);
}
move_filltrav(root);
move_hyptrav(root);
} /* move_hypstates */
void grwrite(chartype c, long num, long *pos)
{
long i;
prefix(c);
for (i = 1; i <= num; i++) {
if ((*pos) >= leftedge && (*pos) - leftedge + 1 < screenwidth)
putchar(che[(long)c]);
(*pos)++;
}
postfix(c);
} /* grwrite */
void move_drawline(long i, long lastline)
{
/* draws one row of the tree diagram by moving up tree */
node *p, *q, *r, *first =NULL, *last =NULL;
long n, j, pos;
boolean extra, done;
Char st;
chartype c, d;
pos = 1;
p = nuroot;
q = nuroot;
extra = false;
if (i == (long)p->ycoord && (p == root || subtree)) {
extra = true;
c = overt;
if (display) {
switch (p->state) {
case '1':
c = onne;
break;
case '0':
c = zerro;
break;
case '?':
c = question;
break;
}
}
if ((subtree))
stwrite("Subtree:", 8, &pos, leftedge, screenwidth);
if (p->index >= 100)
nnwrite(p->index, 3, &pos, leftedge, screenwidth);
else if (p->index >= 10) {
grwrite(c, 1, &pos);
nnwrite(p->index, 2, &pos, leftedge, screenwidth);
} else {
grwrite(c, 2, &pos);
nnwrite(p->index, 1, &pos, leftedge, screenwidth);
}
} else {
if (subtree)
stwrite(" ", 10, &pos, leftedge, screenwidth);
else
stwrite(" ", 2, &pos, leftedge, screenwidth);
}
do {
if (!p->tip) {
r = p->next;
done = false;
do {
if (i >= r->back->ymin && i <= r->back->ymax) {
q = r->back;
done = true;
}
r = r->next;
} while (!(done || r == p));
first = p->next->back;
r = p->next;
while (r->next != p)
r = r->next;
last = r->back;
}
done = (p == q);
n = (long)p->xcoord - (long)q->xcoord;
if (n < 3 && !q->tip)
n = 3;
if (extra) {
n--;
extra = false;
}
if ((long)q->ycoord == i && !done) {
if ((long)q->ycoord > (long)p->ycoord)
d = upcorner;
else
d = downcorner;
c = overt;
if (display) {
switch (q->state) {
case '1':
c = onne;
break;
case '0':
c = zerro;
break;
case '?':
c = question;
break;
}
d = c;
}
if (n > 1) {
grwrite(d, 1, &pos);
grwrite(c, n - 3, &pos);
}
if (q->index >= 100)
nnwrite(q->index, 3, &pos, leftedge, screenwidth);
else if (q->index >= 10) {
grwrite(c, 1, &pos);
nnwrite(q->index, 2, &pos, leftedge, screenwidth);
} else {
grwrite(c, 2, &pos);
nnwrite(q->index, 1, &pos, leftedge, screenwidth);
}
extra = true;
} else if (!q->tip) {
if ((long)last->ycoord > i && (long)first->ycoord < i
&& i != (long)p->ycoord) {
c = up;
if (i < (long)p->ycoord)
st = p->next->back->state;
else
st = p->next->next->back->state;
if (display) {
switch (st) {
case '1':
c = onne;
break;
case '0':
c = zerro;
break;
case '?':
c = question;
break;
}
}
grwrite(c, 1, &pos);
chwrite(' ', n - 1, &pos, leftedge, screenwidth);
} else
chwrite(' ', n, &pos, leftedge, screenwidth);
} else
chwrite(' ', n, &pos, leftedge, screenwidth);
if (p != q)
p = q;
} while (!done);
if ((long)p->ycoord == i && p->tip) {
n = 0;
for (j = 1; j <= nmlngth; j++) {
if (nayme[p->index - 1][j - 1] != '\0')
n = j;
}
chwrite(':', 1, &pos, leftedge, screenwidth);
for (j = 0; j < n; j++)
chwrite(nayme[p->index - 1][j], 1, &pos, leftedge, screenwidth);
}
putchar('\n');
} /* move_drawline */
void move_printree()
{
/* prints out diagram of the tree */
long tipy, i, dow;
if (!subtree)
nuroot = root;
if (changed || newtree)
evaluate(root);
if (display)
move_hypstates();
if (ansi || ibmpc)
printf("\033[2J\033[H");
else
putchar('\n');
tipy = 1;
dow = down;
if (spp * dow > screenlines && !subtree) {
dow--;
}
if (noroot)
printf("(unrooted)");
if (display) {
printf(" ");
makechar(onne);
printf(":1 ");
makechar(question);
printf(":? ");
makechar(zerro);
printf(":0 ");
} else
printf(" ");
if (!earlytree) {
printf("%10.1f Steps", -like);
}
if (display)
printf(" CHAR%3ld", dispchar);
else
printf(" ");
if (!earlytree) {
printf(" %3ld chars compatible\n", compatible);
}
printf(" ");
if (changed && !earlytree) {
if (-like < bestyet) {
printf(" BEST YET!");
bestyet = -like;
} else if (fabs(-like - bestyet) < 0.000001)
printf(" (as good as best)");
else {
if (-like < gotlike)
printf(" better");
else if (-like > gotlike)
printf(" worse!");
}
}
printf("\n");
farthest = 0;
coordinates(nuroot, &tipy, 1.5, &farthest);
vmargin = 4;
treelines = tipy - dow;
if (topedge != 1) {
printf("** %ld lines above screen **\n", topedge - 1);
vmargin++;
}
if ((treelines - topedge + 1) > (screenlines - vmargin))
vmargin++;
for (i = 1; i <= treelines; i++) {
if (i >= topedge && i < topedge + screenlines - vmargin)
move_drawline(i, treelines);
}
if ((treelines - topedge + 1) > (screenlines - vmargin)) {
printf("** %ld", treelines - (topedge - 1 + screenlines - vmargin));
printf(" lines below screen **\n");
}
if (treelines - topedge + vmargin + 1 < screenlines)
putchar('\n');
gotlike = -like;
changed = false;
} /* move_printree */
void arbitree()
{
long i;
root = treenode[0];
add2(treenode[0], treenode[1], treenode[spp], &root,
restoring, wasleft, treenode);
for (i = 3; i <= (spp); i++)
add2(treenode[spp+ i - 3], treenode[i - 1], treenode[spp + i - 2],
&root, restoring, wasleft, treenode);
for (i = 0; i < (nonodes); i++)
in_tree[i] = true;
} /* arbitree */
void yourtree()
{
long i, j;
boolean ok;
root = treenode[0];
add2(treenode[0], treenode[1], treenode[spp], &root,
restoring, wasleft, treenode);
i = 2;
do {
i++;
move_printree();
printf("\nAdd species%3ld: \n", i);
printf(" \n");
for (j = 0; j < nmlngth; j++)
putchar(nayme[i - 1][j]);
do {
printf("\nbefore node (type number): ");
inpnum(&j, &ok);
ok = (ok && ((j >= 1 && j < i) || (j > spp && j < spp + i - 1)));
if (!ok)
printf("Impossible number. Please try again:\n");
} while (!ok);
add2(treenode[j - 1], treenode[i - 1], treenode[spp + i - 2], &root,
restoring, wasleft, treenode);
} while (i != spp);
for (i = 0; i < (nonodes); i++)
in_tree[i] = true;
} /* yourtree */
void initmovenode(node **p, node **grbg, node *q, long len, long nodei,
long *ntips, long *parens, initops whichinit,
pointarray treenode, pointarray nodep, Char *str, Char *ch,
char **treestr)
{
/* initializes a node */
/* LM 7/27 I added this function and the commented lines around */
/* treeread() to get the program running, but all 4 move programs*/
/* are improperly integrated into the v4.0 support files. As is */
/* this is a patchwork function */
boolean minusread;
double valyew, divisor;
switch (whichinit) {
case bottom:
gnutreenode(grbg, p, nodei, chars, zeros);
treenode[nodei - 1] = *p;
break;
case nonbottom:
gnutreenode(grbg, p, nodei, chars, zeros);
break;
case tip:
match_names_to_data (str, treenode, p, spp);
break;
case length:
processlength(&valyew, &divisor, ch, &minusread, treestr, parens);
/* process lengths and discard */
default: /*cases hslength,hsnolength,treewt,unittrwt,iter,*/
break;
}
} /* initmovenode */
void buildtree()
{
long i, j, nextnode;
node *p;
char* treestr;
changed = false;
newtree = false;
switch (how) {
case arb:
arbitree();
break;
case use:
names = (boolean *)Malloc(spp*sizeof(boolean));
firsttree = true; /**/
nodep = NULL; /**/
nextnode = 0; /**/
haslengths = 0; /**/
zeros = (long *)Malloc(chars*sizeof(long)); /**/
for (i = 0; i < chars; i++) /**/
zeros[i] = 0; /**/
treestr = ajStrGetuniquePtr(&phylotrees[0]->Tree);
treeread(&treestr, &root, treenode, &goteof, &firsttree, nodep, &nextnode,
&haslengths, &grbg, initmovenode,false,nonodes);
for (i = spp; i < (nonodes); i++) {
p = treenode[i];
for (j = 1; j <= 3; j++) {
p->stateone = (bitptr)Malloc(words*sizeof(long));
p->statezero = (bitptr)Malloc(words*sizeof(long));
p = p->next;
}
} /* debug: see comment at initmovenode() */
/* treeread(which, ch, &root, treenode, names);*/
for (i = 0; i < (spp); i++)
in_tree[i] = names[i];
free(names);
FClose(intree);
break;
case spec:
yourtree();
break;
}
if (!outgropt)
outgrno = root->next->back->index;
if (outgropt && in_tree[outgrno - 1])
reroot(treenode[outgrno - 1]);
} /* buildtree */
void rearrange()
{
long i, j;
boolean ok1, ok2;
node *p, *q;
printf("Remove everything to the right of which node? ");
inpnum(&i, &ok1);
ok1 = (ok1 && i >= 1 && i < spp * 2 && i != root->index);
if (ok1) {
printf("Add before which node? ");
inpnum(&j, &ok2);
ok2 = (ok2 && j >= 1 && j < spp * 2);
if (ok2) {
ok2 = (treenode[j - 1] != treenode[treenode[i - 1]->back->index - 1]);
p = treenode[j - 1];
while (p != root) {
ok2 = (ok2 && p != treenode[i - 1]);
p = treenode[p->back->index - 1];
}
if (ok1 && ok2) {
what = i;
q = treenode[treenode[i - 1]->back->index - 1];
if (q->next->back->index == i)
fromwhere = q->next->next->back->index;
else
fromwhere = q->next->back->index;
towhere = j;
re_move2(&treenode[i - 1], &q, &root, &wasleft, treenode);
add2(treenode[j - 1], treenode[i - 1], q, &root,
restoring, wasleft, treenode);
}
lastop = rearr;
}
}
changed = (ok1 && ok2);
move_printree();
if (!(ok1 && ok2))
printf("Not a possible rearrangement. Try again: ");
else {
oldwritten =written;
written = false;
}
} /* rearrange */
void tryadd(node *p, node *item, node *nufork, double *place)
{
/* temporarily adds one fork and one tip to the tree.
Records scores in array place */
add2(p, item, nufork, &root, restoring, wasleft, treenode);
evaluate(root);
place[p->index - 1] = -like;
re_move2(&item, &nufork, &root, &wasleft, treenode);
} /* tryadd */
void addpreorder(node *p, node *item, node *nufork, double *place)
{
/* traverses a binary tree, calling function tryadd
at a node before calling tryadd at its descendants */
if (p == NULL)
return;
tryadd(p,item,nufork,place);
if (!p->tip) {
addpreorder(p->next->back, item, nufork, place);
addpreorder(p->next->next->back, item, nufork, place);
}
} /* addpreorder */
void try()
{
/* Remove node, try it in all possible places */
double *place;
long i, j, oldcompat;
double current;
node *q, *dummy, *rute;
boolean tied, better, ok;
printf("Try other positions for which node? ");
inpnum(&i, &ok);
if (!(ok && i >= 1 && i <= nonodes && i != root->index)) {
printf("Not a possible choice! ");
return;
}
printf("WAIT ...\n");
place = (double *)Malloc(nonodes*sizeof(double));
for (j = 0; j < (nonodes); j++)
place[j] = -1.0;
evaluate(root);
current = -like;
oldcompat = compatible;
what = i;
q = treenode[treenode[i - 1]->back->index - 1];
if (q->next->back->index == i)
fromwhere = q->next->next->back->index;
else
fromwhere = q->next->back->index;
rute = root;
if (root->index == treenode[i - 1]->back->index) {
if (treenode[treenode[i - 1]->back->index - 1]->next->back == treenode[i - 1])
rute = treenode[treenode[i - 1]->back->index - 1]->next->next->back;
else
rute = treenode[treenode[i - 1]->back->index - 1]->next->back;
}
re_move2(&treenode[i - 1], &dummy, &root, &wasleft, treenode);
oldleft = wasleft;
root = rute;
addpreorder(root, treenode[i - 1], dummy, place);
wasleft =oldleft;
restoring = true;
add2(treenode[fromwhere - 1], treenode[what - 1],dummy, &root,
restoring, wasleft, treenode);
like = -current;
compatible = oldcompat;
restoring = false;
better = false;
printf(" BETTER: ");
for (j = 1; j <= (nonodes); j++) {
if (place[j - 1] < current && place[j - 1] >= 0.0) {
printf("%3ld:%6.2f", j, place[j - 1]);
better = true;
}
}
if (!better)
printf(" NONE");
printf("\n TIED: ");
tied = false;
for (j = 1; j <= (nonodes); j++) {
if (fabs(place[j - 1] - current) < 1.0e-6 && j != fromwhere) {
if (j < 10)
printf("%2ld", j);
else
printf("%3ld", j);
tied = true;
}
}
if (tied)
printf(":%6.2f\n", current);
else
printf("NONE\n");
changed = true;
free(place);
} /* try */
void undo()
{
/* restore to tree before last rearrangement */
long temp;
boolean btemp;
node *q;
switch (lastop) {
case rearr:
restoring = true;
oldleft = wasleft;
re_move2(&treenode[what - 1], &q, &root, &wasleft, treenode);
btemp = wasleft;
wasleft = oldleft;
add2(treenode[fromwhere - 1], treenode[what - 1],q, &root,
restoring, wasleft, treenode);
wasleft = btemp;
restoring = false;
temp = fromwhere;
fromwhere = towhere;
towhere = temp;
changed = true;
break;
case flipp:
q = treenode[atwhat - 1]->next->back;
treenode[atwhat - 1]->next->back =
treenode[atwhat - 1]->next->next->back;
treenode[atwhat - 1]->next->next->back = q;
treenode[atwhat - 1]->next->back->back = treenode[atwhat - 1]->next;
treenode[atwhat - 1]->next->next->back->back =
treenode[atwhat - 1]->next->next;
break;
case reroott:
restoring = true;
temp = oldoutgrno;
oldoutgrno = outgrno;
outgrno = temp;
reroot(treenode[outgrno - 1]);
restoring = false;
break;
case none:
/* blank case */
break;
}
move_printree();
if (lastop == none) {
printf("No operation to undo! \n");
return;
}
btemp = oldwritten;
oldwritten = written;
written = btemp;
} /* undo */
void treewrite(boolean done)
{
/* write out tree to a file */
if (!done)
move_printree();
if (waswritten && ch == 'N')
return;
col = 0;
treeout(root, 1, &col, root);
printf("\nTree written to file \"%s\"\n\n", outtreename);
waswritten = true;
written = true;
FClose(outtree);
#ifdef MAC
fixmacfile(outtreename);
#endif
}
/* treewrite */
void clade()
{
/* pick a subtree and show only that on screen */
long i;
boolean ok;
printf("Select subtree rooted at which node (0 for whole tree)? ");
inpnum(&i, &ok);
ok = (ok && (unsigned)(i <= nonodes));
if (ok) {
subtree = (i > 0);
if (subtree)
nuroot = treenode[i - 1];
else
nuroot = root;
}
move_printree();
if (!ok)
printf("Not possible to use this node. ");
} /* clade */
void flip()
{
/* flip at a node left-right */
long i;
boolean ok;
node *p;
printf("Flip branches at which node? ");
inpnum(&i, &ok);
ok = (ok && i > spp && i <= nonodes);
if (ok) {
p = treenode[i - 1]->next->back;
treenode[i - 1]->next->back = treenode[i - 1]->next->next->back;
treenode[i - 1]->next->next->back = p;
treenode[i - 1]->next->back->back = treenode[i - 1]->next;
treenode[i - 1]->next->next->back->back = treenode[i - 1]->next->next;
atwhat = i;
lastop = flipp;
}
move_printree();
if (ok) {
oldwritten = written;
written = false;
return;
}
if (i >= 1 && i <= spp)
printf("Can't flip there. ");
else
printf("No such node. ");
} /* flip */
void changeoutgroup()
{
long i;
boolean ok;
oldoutgrno = outgrno;
do {
printf("Which node should be the new outgroup? ");
inpnum(&i, &ok);
ok = (ok && in_tree[i - 1] && i >= 1 && i <= nonodes &&
i != root->index);
if (ok)
outgrno = i;
} while (!ok);
if (in_tree[outgrno - 1])
reroot(treenode[outgrno - 1]);
changed = true;
lastop = reroott;
move_printree();
oldwritten = written;
written = false;
} /* changeoutgroup */
void redisplay()
{
boolean done=false;
waswritten = false;
do {
fprintf(stderr, "NEXT? (R # + - S . T U W O F H J K L C ? X Q) ");
fprintf(stderr, "(? for Help): ");
#ifdef WIN32
phyFillScreenColor();
#endif
fflush(stdout);
scanf("%c%*[^\n]", &ch);
getchar();
if (ch == '\n')
ch = ' ';
uppercase(&ch);
if (strchr("R#+-S.TUWOFHJKLC?XQ",ch) != NULL){
switch (ch) {
case 'R':
rearrange();
break;
case '#':
nextinc(&dispchar, &dispword, &dispbit, chars, bits, &display,
numsteps, weight);
move_printree();
break;
case '+':
nextchar(&dispchar, &dispword, &dispbit, chars, bits, &display);
move_printree();
break;
case '-':
prevchar(&dispchar, &dispword, &dispbit, chars, bits, &display);
move_printree();
break;
case 'S':
show(&dispchar, &dispword, &dispbit, chars, bits, &display);
move_printree();
break;
case '.':
move_printree();
break;
case 'T':
try();
break;
case 'U':
undo();
break;
case 'W':
treewrite(done);
break;
case 'O':
changeoutgroup();
break;
case 'F':
flip();
break;
case 'H':
window(left, &leftedge, &topedge, hscroll, vscroll, treelines,
screenlines, screenwidth, farthest, subtree);
move_printree();
break;
case 'J':
window(downn, &leftedge, &topedge, hscroll, vscroll, treelines,
screenlines, screenwidth, farthest, subtree);
move_printree();
break;
case 'K':
window(upp, &leftedge, &topedge, hscroll, vscroll, treelines,
screenlines, screenwidth, farthest, subtree);
move_printree();
break;
case 'L':
window(right, &leftedge, &topedge, hscroll, vscroll, treelines,
screenlines, screenwidth, farthest, subtree);
move_printree();
break;
case 'C':
clade();
break;
case '?':
help("character");
move_printree();
break;
case 'X':
done = true;
break;
case 'Q':
done = true;
break;
}
}
} while (!done);
if (!written) {
do {
fprintf(stderr,"Do you want to write out the tree to a file? (Y or N): ");
#ifdef WIN32
phyFillScreenColor();
#endif
scanf("%c%*[^\n]", &ch);
getchar();
if (ch == '\n')
ch = ' ';
} while (ch != 'Y' && ch != 'y' && ch != 'N' && ch != 'n');
}
if (ch == 'Y' || ch == 'y')
treewrite(done);
} /* redisplay */
void treeconstruct()
{
/* constructs a binary tree from the pointers in treenode. */
restoring = false;
subtree = false;
display = false;
dispchar = 0;
fullset = (1L << (bits + 1)) - (1L << 1);
earlytree = true;
buildtree();
waswritten = false;
printf("\nComputing steps needed for compatibility in characters...\n\n");
newtree = true;
earlytree = false;
move_printree();
bestyet = -like;
gotlike = -like;
lastop = none;
newtree = false;
written = false;
redisplay();
} /* treeconstruct */
int main(int argc, Char *argv[])
{ /* Interactive mixed parsimony */
/* reads in spp, chars, and the data. Then calls treeconstruct to */
/* construct the tree and query the user */
#ifdef MAC
argc = 1; /* macsetup("Move",""); */
argv[0] = "Move";
#endif
init(argc, argv);
emboss_getoptions("fmove", argc, argv);
progname = argv[0];
topedge = 1;
leftedge = 1;
ibmpc = IBMCRT;
ansi = ANSICRT;
root = NULL;
bits = 8*sizeof(long) - 1;
doinput();
configure();
treeconstruct();
FClose(outtree);
#ifdef MAC
fixmacfile(outtreename);
#endif
#ifdef WIN32
phyRestoreConsoleAttributes();
#endif
embExit();
return 0;
} /* Interactive mixed parsimony */
PHYLIPNEW-3.69.650/src/dollo.c 0000664 0001750 0001750 00000025032 10775447511 012347 0000000 0000000 #include "phylip.h"
#include "disc.h"
#include "dollo.h"
/* version 3.6. (c) Copyright 1993-2004 by the University of Washington.
Written by Joseph Felsenstein, Akiko Fuseki, Sean Lamont, and Andrew Keeffe.
Permission is granted to copy and use this program provided no fee is
charged for it and provided that this copyright notice is not removed. */
void correct(node *p, long fullset, boolean dollo,
bitptr zeroanc, pointptr treenode)
{ /* get final states for intermediate nodes */
long i;
long z0, z1, s0, s1, temp;
if (p->tip)
return;
for (i = 0; i < (words); i++) {
if (p->back == NULL) {
s0 = zeroanc[i];
s1 = fullset & (~zeroanc[i]);
} else {
s0 = treenode[p->back->index - 1]->statezero[i];
s1 = treenode[p->back->index - 1]->stateone[i];
}
z0 = (s0 & p->statezero[i]) |
(p->next->back->statezero[i] & p->next->next->back->statezero[i]);
z1 = (s1 & p->stateone[i]) |
(p->next->back->stateone[i] & p->next->next->back->stateone[i]);
if (dollo) {
temp = z0 & (~(zeroanc[i] & z1));
z1 &= ~(fullset & (~zeroanc[i]) & z0);
z0 = temp;
}
temp = fullset & (~z0) & (~z1);
p->statezero[i] = z0 | (temp & s0 & (~s1));
p->stateone[i] = z1 | (temp & s1 & (~s0));
}
} /* correct */
void fillin(node *p)
{
/* Sets up for each node in the tree two statesets.
stateone and statezero are the sets of character
states that must be 1 or must be 0, respectively,
in a most parsimonious reconstruction, based on the
information at or above this node. Note that this
state assignment may change based on information further
down the tree. If a character is in both sets it is in
state "P". If in neither, it is "?". */
long i;
for (i = 0; i < words; i++) {
p->stateone[i] = p->next->back->stateone[i] |
p->next->next->back->stateone[i];
p->statezero[i] = p->next->back->statezero[i] |
p->next->next->back->statezero[i];
}
} /* fillin */
void postorder(node *p)
{
/* traverses a binary tree, calling PROCEDURE fillin at a
node's descendants before calling fillin at the node */
/* used in dollop, dolmove, & move */
if (p->tip)
return;
postorder(p->next->back);
postorder(p->next->next->back);
fillin(p);
} /* postorder */
void count(long *stps, bitptr zeroanc, steptr numszero, steptr numsone)
{
/* counts the number of steps in a branch of the tree.
The program spends much of its time in this PROCEDURE */
/* used in dolpenny & move */
long i, j, l;
j = 1;
l = 0;
for (i = 0; i < (chars); i++) {
l++;
if (l > bits) {
l = 1;
j++;
}
if (((1L << l) & stps[j - 1]) != 0) {
if (((1L << l) & zeroanc[j - 1]) != 0)
numszero[i] += weight[i];
else
numsone[i] += weight[i];
}
}
} /* count */
void filltrav(node *r)
{
/* traverse to fill in interior node states */
if (r->tip)
return;
filltrav(r->next->back);
filltrav(r->next->next->back);
fillin(r);
} /* filltrav */
void hyprint(struct htrav_vars *Hyptrav, boolean *unknown,
bitptr dohyp, Char *guess)
{
/* print out states at node */
long i, j, k;
char l;
boolean dot, a0, a1, s0, s1;
if (Hyptrav->bottom)
fprintf(outfile, "root ");
else
fprintf(outfile, "%3ld ", Hyptrav->r->back->index - spp);
if (Hyptrav->r->tip) {
for (i = 0; i < nmlngth; i++)
putc(nayme[Hyptrav->r->index - 1][i], outfile);
} else
fprintf(outfile, "%4ld ", Hyptrav->r->index - spp);
if (Hyptrav->nonzero)
fprintf(outfile, " yes ");
else if (*unknown)
fprintf(outfile, " ? ");
else
fprintf(outfile, " no ");
for (j = 1; j <= (chars); j++) {
newline(outfile, j, 40, nmlngth + 17);
k = (j - 1) / bits + 1;
l = (j - 1) % bits + 1;
dot = (((1L << l) & dohyp[k - 1]) == 0 && guess[j - 1] == '?');
s0 = (((1L << l) & Hyptrav->r->statezero[k - 1]) != 0);
s1 = (((1L << l) & Hyptrav->r->stateone[k - 1]) != 0);
a0 = (((1L << l) & Hyptrav->zerobelow->bits_[k - 1]) != 0);
a1 = (((1L << l) & Hyptrav->onebelow->bits_[k - 1]) != 0);
dot = (dot || (a1 == s1 && a0 == s0));
if (dot)
putc('.', outfile);
else {
if (s0) {
if (s1)
putc('P', outfile);
else
putc('0', outfile);
} else if (s1)
putc('1', outfile);
else
putc('?', outfile);
}
if (j % 5 == 0)
putc(' ', outfile);
}
putc('\n', outfile);
} /* hyprint */
void hyptrav(node *r_, boolean *unknown, bitptr dohyp, long fullset,
boolean dollo, Char *guess, pointptr treenode, gbit *garbage,
bitptr zeroanc, bitptr oneanc)
{
/* compute, print out states at one interior node */
struct htrav_vars HypVars;
long i;
HypVars.r = r_;
disc_gnu(&HypVars.zerobelow, &garbage);
disc_gnu(&HypVars.onebelow, &garbage);
if (!HypVars.r->tip)
correct(HypVars.r, fullset, dollo, zeroanc, treenode);
HypVars.bottom = (HypVars.r->back == NULL);
HypVars.nonzero = false;
if (HypVars.bottom) {
memcpy(HypVars.zerobelow->bits_, zeroanc, words*sizeof(long));
memcpy(HypVars.onebelow->bits_, oneanc, words*sizeof(long));
} else {
memcpy(HypVars.zerobelow->bits_,
treenode[HypVars.r->back->index - 1]->statezero, words*sizeof(long));
memcpy(HypVars.onebelow->bits_,
treenode[HypVars.r->back->index - 1]->stateone, words*sizeof(long));
}
for (i = 0; i < (words); i++)
HypVars.nonzero = (HypVars.nonzero ||
((HypVars.r->stateone[i] & HypVars.zerobelow->bits_[i])
| (HypVars.r->statezero[i]
& HypVars.onebelow->bits_[i])) != 0);
hyprint(&HypVars,unknown,dohyp, guess);
if (!HypVars.r->tip) {
hyptrav(HypVars.r->next->back, unknown,dohyp, fullset, dollo, guess,
treenode, garbage, zeroanc, oneanc);
hyptrav(HypVars.r->next->next->back, unknown,dohyp, fullset, dollo,
guess, treenode, garbage, zeroanc, oneanc);
}
disc_chuck(HypVars.zerobelow, &garbage);
disc_chuck(HypVars.onebelow, &garbage);
} /* hyptrav */
void hypstates(long fullset, boolean dollo, Char *guess, pointptr treenode,
node *root, gbit *garbage, bitptr zeroanc, bitptr oneanc)
{
/* fill in and describe states at interior nodes */
/* used in dollop & dolpenny */
boolean unknown = false;
bitptr dohyp;
long i, j, k;
for (i = 0; i < (words); i++) {
zeroanc[i] = 0;
oneanc[i] = 0;
}
for (i = 0; i < (chars); i++) {
j = i / bits + 1;
k = i % bits + 1;
if (guess[i] == '0')
zeroanc[j - 1] = ((long)zeroanc[j - 1]) | (1L << k);
if (guess[i] == '1')
oneanc[j - 1] = ((long)oneanc[j - 1]) | (1L << k);
unknown = (unknown || guess[i] == '?');
}
dohyp = (bitptr)Malloc(words*sizeof(long));
for (i = 0; i < words; i++)
dohyp[i] = zeroanc[i] | oneanc[i];
filltrav(root);
fprintf(outfile, "From To Any Steps?");
fprintf(outfile, " State at upper node\n");
fprintf(outfile, " ");
fprintf(outfile, " ( . means same as in the node below it on tree)\n\n");
hyptrav(root, &unknown,dohyp, fullset, dollo, guess, treenode, garbage,
zeroanc, oneanc);
free(dohyp);
} /* hypstates */
void drawline(long i, double scale, node *root)
{
/* draws one row of the tree diagram by moving up tree */
node *p, *q, *r, *first =NULL, *last =NULL;
long n, j;
boolean extra, done;
p = root;
q = root;
extra = false;
if (i == (long)p->ycoord && p == root) {
if (p->index - spp >= 10)
fprintf(outfile, "-%2ld", p->index - spp);
else
fprintf(outfile, "--%ld", p->index - spp);
extra = true;
} else
fprintf(outfile, " ");
do {
if (!p->tip) {
r = p->next;
done = false;
do {
if (i >= r->back->ymin && i <= r->back->ymax) {
q = r->back;
done = true;
}
r = r->next;
} while (!(done || r == p));
first = p->next->back;
r = p->next;
while (r->next != p)
r = r->next;
last = r->back;
}
done = (p == q);
n = (long)(scale * (p->xcoord - q->xcoord) + 0.5);
if (n < 3 && !q->tip)
n = 3;
if (extra) {
n--;
extra = false;
}
if ((long)q->ycoord == i && !done) {
putc('+', outfile);
if (!q->tip) {
for (j = 1; j <= n - 2; j++)
putc('-', outfile);
if (q->index - spp >= 10)
fprintf(outfile, "%2ld", q->index - spp);
else
fprintf(outfile, "-%ld", q->index - spp);
extra = true;
} else {
for (j = 1; j < n; j++)
putc('-', outfile);
}
} else if (!p->tip) {
if ((long)last->ycoord > i && (long)first->ycoord < i
&& i != (long)p->ycoord) {
putc('!', outfile);
for (j = 1; j < n; j++)
putc(' ', outfile);
} else {
for (j = 1; j <= n; j++)
putc(' ', outfile);
}
} else {
for (j = 1; j <= n; j++)
putc(' ', outfile);
}
if (p != q)
p = q;
} while (!done);
if ((long)p->ycoord == i && p->tip) {
for (j = 0; j < nmlngth; j++)
putc(nayme[p->index - 1][j], outfile);
}
putc('\n', outfile);
} /* drawline */
void printree(double f, boolean treeprint, node *root)
{
/* prints out diagram of the tree */
/* used in dollop & dolpenny */
long i, tipy, dummy;
double scale;
putc('\n', outfile);
if (!treeprint)
return;
putc('\n', outfile);
tipy = 1;
dummy = 0;
coordinates(root, &tipy, f, &dummy);
scale = 1.5;
putc('\n', outfile);
for (i = 1; i <= (tipy - down); i++)
drawline(i, scale, root);
putc('\n', outfile);
} /* printree */
void writesteps(boolean weights, boolean dollo, steptr numsteps)
{ /* write number of steps */
/* used in dollop & dolpenny */
long i, j, k;
if (weights)
fprintf(outfile, "weighted");
if (dollo)
fprintf(outfile, " reversions ");
else
fprintf(outfile, " polymorphisms ");
fprintf(outfile, "in each character:\n");
fprintf(outfile, " ");
for (i = 0; i <= 9; i++)
fprintf(outfile, "%4ld", i);
fprintf(outfile, "\n *-----------------------------------------\n");
for (i = 0; i <= (chars / 10); i++) {
fprintf(outfile, "%5ld", i * 10);
putc('!', outfile);
for (j = 0; j <= 9; j++) {
k = i * 10 + j;
if (k == 0 || k > chars)
fprintf(outfile, " ");
else
fprintf(outfile, "%4ld", numsteps[k - 1] + extras[k - 1]);
}
putc('\n', outfile);
}
putc('\n', outfile);
} /* writesteps */
PHYLIPNEW-3.69.650/src/treedistpair.c 0000664 0001750 0001750 00000111135 11605067345 013731 0000000 0000000 /* version 3.6. (c) Copyright 1993-2005 by the University of Washington.
Written by Dan Fineman, Joseph Felsenstein, Mike Palczewski, Hisashi Horino,
Akiko Fuseki, Sean Lamont, and Andrew Keeffe.
Permission is granted to copy and use this program provided no fee
is charged for it and provided that this copyright notice is not removed. */
#include "phylip.h"
#include "cons.h"
typedef enum { PHYLIPSYMMETRIC, PHYLIPBSD } distance_type;
/* The following extern's refer to things declared in cons.c */
extern int tree_pairing;
extern Char intreename[FNMLNGTH], intree2name[FNMLNGTH], outtreename[FNMLNGTH];
extern node *root;
const char* outfilename;
AjPFile embossoutfile;
long trees_in_1, trees_in_2;
extern long numopts, outgrno, col;
extern long maxgrp; /* max. no. of groups in all trees found */
extern boolean trout, firsttree, noroot, outgropt, didreroot, prntsets,
progress, treeprint, goteof;
extern pointarray treenode, nodep;
extern group_type **grouping, **grping2, **group2;/* to store groups found */
extern long **order, **order2, lasti;
extern group_type *fullset;
extern node *grbg;
extern long tipy;
extern double **timesseen, **tmseen2, **times2;
extern double trweight, ntrees;
static distance_type dtype;
static long output_scheme;
AjPPhyloTree* phylotrees = NULL;
AjPPhyloTree* phylomoretrees = NULL;
#ifndef OLDC
/* function prototpes */
void assign_tree(group_type **, pattern_elm ***, long, long *);
boolean group_is_null(group_type **, long);
void compute_distances(pattern_elm ***, long, long);
void free_patterns(pattern_elm ***, long);
void produce_square_matrix(long, long *);
void produce_full_matrix(long, long, long *);
void output_submenu(void);
void pairing_submenu(void);
void read_second_file(pattern_elm ***, long, long, AjPPhyloTree* trees);
//void getoptions(void);
void emboss_getoptions(char *pgm, int argc, char *argv[]);
void assign_lengths(double **lengths, pattern_elm ***pattern_array,
long tree_index);
void print_header(long trees_in_1, long trees_in_2);
void output_distances(long trees_in_1, long trees_in_2);
void output_long_distance(long diffl, long tree1, long tree2,
long trees_in_1, long trees_in_2);
void output_matrix_long(long diffl, long tree1, long tree2, long trees_in_1,
long trees_in_2);
void output_matrix_double(double diffl, long tree1, long tree2, long trees_in_1,
long trees_in_2);
void output_double_distance(double diffd, long tree1, long tree2,
long trees_in_1, long trees_in_2);
long symetric_diff(group_type **tree1, group_type **tree2,
long ntree1, long ntree2, long patternsz1, long patternsz2);
double bsd_tree_diff(group_type **tree1, group_type **tree2, long ntree1,
long ntree2, double* lengths1, double *lengths2,
long patternsz1, long patternsz2);
void tree_diff(group_type **tree1, group_type **tree2, double *lengths1,
double* lengths2, long patternsz1, long patternsz2, long ntree1,
long ntree2, long trees_in_1, long trees_in_2);
void print_line_heading(long tree);
int get_num_columns(void);
void print_matrix_heading(long tree, long maxtree);
/* function prototpes */
#endif
void assign_lengths(double **lengths, pattern_elm ***pattern_array,
long tree_index)
{
*lengths = pattern_array[0][tree_index]->length;
}
void assign_tree(group_type **treeN, pattern_elm ***pattern_array,
long tree_index, long *pattern_size)
{ /* set treeN to be the tree_index-th tree in pattern_elm */
long i;
for ( i = 0 ; i < setsz ; i++ ) {
treeN[i] = pattern_array[i][tree_index]->apattern;
}
*pattern_size = *pattern_array[0][tree_index]->patternsize;
} /* assign_tree */
boolean group_is_null(group_type **treeN, long index)
{
/* Check to see if a given index to a tree array points to an empty
group */
long i;
for ( i = 0 ; i < setsz ; i++ )
if (treeN[i][index] != (group_type) 0)
return false;
/* If we've gotten this far, then the index is to an empty group in
the tree. */
return true;
} /* group_is_null */
double bsd_tree_diff(group_type **tree1, group_type **tree2,
long ntree1, long ntree2, double *lengths1,
double* lengths2, long patternsz1, long patternsz2)
{
/* Compute the difference between 2 given trees. Return
that value as a double. */
long index1, index2;
double return_value = 0;
boolean match_found;
long i;
if ( group_is_null(tree1, 0) || group_is_null(tree2, 0) ) {
printf ("Error computing tree difference between tree %ld and tree %ld\n",
ntree1, ntree2);
embExitBad();
}
for ( index1 = 0; index1 < patternsz1; index1++ ) {
if ( !group_is_null(tree1, index1) ) {
if ( lengths1[index1] == -1 ) {
printf(
"Error: tree %ld is missing a length from at least one branch\n",
ntree1);
embExitBad();
}
}
}
for ( index2 = 0; index2 < patternsz2; index2++ ) {
if ( !group_is_null(tree2, index2) ) {
if ( lengths2[index2] == -1 ) {
printf(
"Error: tree %ld is missing a length from at least one branch\n",
ntree2);
embExitBad();
}
}
}
for ( index1 = 0 ; index1 < patternsz1; index1++ ) {
/* For every element in the first tree, see if there's
a match to it in the second tree. */
match_found = false;
if ( group_is_null(tree1, index1) ) {
/* When we've gone over all the elements in tree1, greater
number of elements in tree2 will constitute that much more
of a difference... */
while ( !group_is_null(tree2, index1) ) {
return_value += pow(lengths1[index1], 2);
index1++;
}
break;
}
for ( index2 = 0 ; index2 < patternsz2 ; index2++ ) {
/* For every element in the second tree, see if any match
the current element in the first tree. */
if ( group_is_null(tree2, index2) ) {
/* When we've gone over all the elements in tree2 */
match_found = false;
break;
}
else {
/* Tentatively set match_found; will be changed later if
neccessary. . . */
match_found = true;
for ( i = 0 ; i < setsz ; i++ ) {
/* See if we've got a match, */
if ( tree1[i][index1] != tree2[i][index2] )
match_found = false;
}
if ( match_found == true ) {
break;
}
}
}
if ( match_found == false ) {
return_value += pow(lengths1[index1], 2);
}
}
for ( index2 = 0 ; index2 < patternsz2 ; index2++ ) {
/* For every element in the second tree, see if there's
a match to it in the first tree. */
match_found = false;
if ( group_is_null(tree2, index2) ) {
/* When we've gone over all the elements in tree2, greater
number of elements in tree1 will constitute that much more
of a difference... */
while ( !group_is_null(tree1, index2) ) {
return_value += pow(lengths2[index2], 2);
index2++;
}
break;
}
for ( index1 = 0 ; index1 < patternsz1 ; index1++ ) {
/* For every element in the first tree, see if any match
the current element in the second tree. */
if ( group_is_null(tree1, index1) ) {
/* When we've gone over all the elements in tree2 */
match_found = false;
break;
}
else {
/* Tentatively set match_found; will be changed later if
neccessary. . . */
match_found = true;
for ( i = 0 ; i < setsz ; i++ ) {
/* See if we've got a match, */
if ( tree1[i][index1] != tree2[i][index2] )
match_found = false;
}
if ( match_found == true ) {
return_value += pow(lengths1[index1] - lengths2[index2], 2);
break;
}
}
}
if ( match_found == false ) {
return_value += pow(lengths2[index2], 2);
}
}
if (return_value > 0.0)
return_value = sqrt(return_value);
else
return_value = 0.0;
return return_value;
}
long symetric_diff(group_type **tree1, group_type **tree2,
long ntree1, long ntree2, long patternsz1, long patternsz2)
{
/* Compute the symmetric difference between 2 given trees. Return
that value as a long. */
long index1, index2, return_value = 0;
boolean match_found;
long i;
if (group_is_null (tree1, 0) || group_is_null (tree2, 0)) {
printf ("Error computing tree difference.\n");
return 0;
}
for (index1 = 0 ; index1 < patternsz1 ; index1++) {
/* For every element in the first tree, see if there's
a match to it in the second tree. */
match_found = false;
if (group_is_null (tree1, index1)) {
/* When we've gone over all the elements in tree1, greater
number of elements in tree2 will constitute that much more
of a difference... */
while (! group_is_null (tree2, index1)) {
return_value++;
index1++;
}
break;
}
for (index2 = 0 ; index2 < patternsz2 ; index2++) {
/* For every element in the second tree, see if any match
the current element in the first tree. */
if (group_is_null (tree2, index2)) {
/* When we've gone over all the elements in tree2 */
match_found = false;
break;
} else {
/* Tentatively set match_found; will be changed later if
neccessary. . . */
match_found = true;
for (i = 0 ; i < setsz ; i++) {
/* See if we've got a match, */
if (tree1[i][index1] != tree2[i][index2])
match_found = false;
}
if (match_found == true) {
/* If the previous loop ran from 0 to setsz without setting
match_found to false, */
break;
}
}
}
if (match_found == false) {
return_value++;
}
}
return return_value;
} /* symetric_diff */
void output_double_distance(double diffd, long tree1, long tree2,
long trees_in_1, long trees_in_2)
{
switch (tree_pairing) {
case ADJACENT_PAIRS:
if (output_scheme == VERBOSE ) {
fprintf (outfile, "Trees %ld and %ld: %e\n", tree1, tree2, diffd);
} else if (output_scheme == SPARSE) {
fprintf (outfile, "%ld %ld %e\n", tree1, tree2, diffd);
}
break;
case ALL_IN_FIRST:
if (output_scheme == VERBOSE) {
fprintf (outfile, "Trees %ld and %ld: %e\n", tree1, tree2, diffd);
} else if (output_scheme == SPARSE) {
fprintf (outfile, "%ld %ld %e\n", tree1, tree2, diffd );
} else if (output_scheme == FULL_MATRIX) {
output_matrix_double(diffd, tree1, tree2, trees_in_1, trees_in_2);
}
break;
case CORR_IN_1_AND_2:
if (output_scheme == VERBOSE) {
fprintf (outfile, "Tree pair %ld: %e\n", tree1, diffd);
} else if (output_scheme == SPARSE) {
fprintf (outfile, "%ld %e\n", tree1, diffd);
}
break;
case ALL_IN_1_AND_2:
if (output_scheme == VERBOSE )
fprintf (outfile, "Trees %ld and %ld: %e\n", tree1, tree2, diffd);
else if (output_scheme == SPARSE)
fprintf (outfile, "%ld %ld %e\n", tree1, tree2, diffd);
else if (output_scheme == FULL_MATRIX) {
output_matrix_double(diffd, tree1, tree2, trees_in_1, trees_in_2);
}
break;
}
} /* output_double_distance */
void print_matrix_heading(long tree, long maxtree)
{
long i;
if ( tree_pairing == ALL_IN_1_AND_2 ) {
fprintf(outfile, "\n\nFirst\\ Second tree file:\n");
fprintf(outfile, "tree \\\n");
fprintf(outfile, "file: \\");
} else fprintf(outfile, "\n\n ");
for ( i = tree ; i <= maxtree ; i++ ) {
if ( dtype == PHYLIPSYMMETRIC )
fprintf(outfile, "%5ld ", i);
else
fprintf(outfile, " %7ld ", i);
}
fprintf(outfile, "\n");
if ( tree_pairing == ALL_IN_1_AND_2 )
fprintf(outfile, " \\");
else
fprintf(outfile, " \\");
for ( i = tree ; i <= maxtree ; i++ ) {
if ( dtype == PHYLIPSYMMETRIC )
fprintf(outfile, "------");
else fprintf(outfile, "------------");
}
}
void print_line_heading(long tree)
{
if ( tree_pairing == ALL_IN_1_AND_2 )
fprintf(outfile, "\n%4ld |", tree);
else fprintf(outfile, "\n%5ld |", tree);
}
void output_matrix_double(double diffl, long tree1, long tree2, long trees_in_1,
long trees_in_2)
{
if ( tree1 == 1 && ((tree2 - 1) % get_num_columns() == 0 || tree2 == 1 )) {
if ( (tree_pairing == ALL_IN_FIRST && tree2 + get_num_columns() - 1
< trees_in_1) ||
(tree_pairing == ALL_IN_1_AND_2 && tree2 + get_num_columns() - 1
< trees_in_2)) {
print_matrix_heading(tree2, tree2 + get_num_columns() - 1);
} else {
if ( tree_pairing == ALL_IN_FIRST)
print_matrix_heading(tree2, trees_in_1);
else
print_matrix_heading(tree2, trees_in_2);
}
}
if ( (tree2 - 1) % get_num_columns() == 0 || tree2 == 1) {
print_line_heading(tree1);
}
fprintf(outfile, " %9g ", diffl);
if ((tree_pairing == ALL_IN_FIRST && tree1 == trees_in_1 && tree2 ==
trees_in_1) || (tree_pairing == ALL_IN_1_AND_2 && tree1 == trees_in_1 &&
tree2 == trees_in_2))
fprintf(outfile, "\n\n\n");
} /* output_matrix_double */
void output_matrix_long(long diffl, long tree1, long tree2, long trees_in_1,
long trees_in_2)
{
if ( tree1 == 1 && ((tree2 - 1) % get_num_columns() == 0 || tree2 == 1 )) {
if ( (tree_pairing == ALL_IN_FIRST && tree2 + get_num_columns() - 1
< trees_in_1) ||
(tree_pairing == ALL_IN_1_AND_2 && tree2 + get_num_columns() - 1
< trees_in_2)) {
print_matrix_heading(tree2, tree2 + get_num_columns() - 1);
} else {
if ( tree_pairing == ALL_IN_FIRST)
print_matrix_heading(tree2, trees_in_1);
else
print_matrix_heading(tree2, trees_in_2);
}
}
if ( (tree2 - 1) % get_num_columns() == 0 || tree2 == 1) {
print_line_heading(tree1);
}
fprintf(outfile, "%4ld ", diffl);
if ((tree_pairing == ALL_IN_FIRST && tree1 == trees_in_1 && tree2 ==
trees_in_1) || (tree_pairing == ALL_IN_1_AND_2 && tree1 == trees_in_1 &&
tree2 == trees_in_2))
fprintf(outfile, "\n\n\n");
} /* output_matrix_long */
void output_long_distance(long diffl, long tree1, long tree2, long trees_in_1,
long trees_in_2)
{
switch (tree_pairing) {
case ADJACENT_PAIRS:
if (output_scheme == VERBOSE ) {
fprintf (outfile, "Trees %ld and %ld: %ld\n", tree1, tree2, diffl);
} else if (output_scheme == SPARSE) {
fprintf (outfile, "%ld %ld %ld\n", tree1, tree2, diffl);
}
break;
case ALL_IN_FIRST:
if (output_scheme == VERBOSE) {
fprintf (outfile, "Trees %ld and %ld: %ld\n", tree1, tree2, diffl);
} else if (output_scheme == SPARSE) {
fprintf (outfile, "%ld %ld %ld\n", tree1, tree2, diffl );
} else if (output_scheme == FULL_MATRIX) {
output_matrix_long(diffl, tree1, tree2, trees_in_1, trees_in_2);
}
break;
case CORR_IN_1_AND_2:
if (output_scheme == VERBOSE) {
fprintf (outfile, "Tree pair %ld: %ld\n", tree1, diffl);
} else if (output_scheme == SPARSE) {
fprintf (outfile, "%ld %ld\n", tree1, diffl);
}
break;
case ALL_IN_1_AND_2:
if (output_scheme == VERBOSE)
fprintf (outfile, "Trees %ld and %ld: %ld\n", tree1, tree2, diffl);
else if (output_scheme == SPARSE)
fprintf (outfile, "%ld %ld %ld\n", tree1, tree2, diffl);
else if (output_scheme == FULL_MATRIX ) {
output_matrix_long(diffl, tree1, tree2, trees_in_1, trees_in_2);
}
break;
}
}
void tree_diff(group_type **tree1, group_type **tree2, double *lengths1,
double* lengths2, long patternsz1, long patternsz2,
long ntree1, long ntree2, long trees_in_1, long trees_in_2)
{
long diffl;
double diffd;
switch (dtype) {
case PHYLIPSYMMETRIC:
diffl = symetric_diff (tree1, tree2, ntree1, ntree2,
patternsz1, patternsz2);
diffl += symetric_diff (tree2, tree1, ntree1, ntree2,
patternsz2, patternsz1);
output_long_distance(diffl, ntree1, ntree2, trees_in_1, trees_in_2);
break;
case PHYLIPBSD:
diffd = bsd_tree_diff(tree1, tree2, ntree1, ntree2,
lengths1, lengths2, patternsz1, patternsz2);
output_double_distance(diffd, ntree1, ntree2, trees_in_1, trees_in_2);
break;
}
} /* tree_diff */
int get_num_columns(void)
{
if ( dtype == PHYLIPSYMMETRIC )
return 10;
else return 7;
} /* get_num_columns */
void compute_distances(pattern_elm ***pattern_array, long trees_in_1,
long trees_in_2)
{
/* Compute symmetric distances between arrays of trees */
long tree_index, end_tree, index1, index2, index3;
group_type **treeA, **treeB;
long patternsz1, patternsz2;
double *length1 = NULL, *length2 = NULL;
int num_columns = get_num_columns();
index1 = 0;
/* Put together space for treeA and treeB */
treeA = (group_type **) Malloc (setsz * sizeof (group_type *));
treeB = (group_type **) Malloc (setsz * sizeof (group_type *));
print_header(trees_in_1, trees_in_2);
switch (tree_pairing) {
case ADJACENT_PAIRS:
/* For every tree, compute the distance between it and the tree
at the next location; do this in both directions */
end_tree = trees_in_1 - 1;
for (tree_index = 0 ; tree_index < end_tree ; tree_index += 2) {
assign_tree (treeA, pattern_array, tree_index, &patternsz1);
assign_tree (treeB, pattern_array, tree_index + 1, &patternsz2);
assign_lengths(&length1, pattern_array, tree_index);
assign_lengths(&length2, pattern_array, tree_index + 1);
tree_diff (treeA, treeB, length1, length2, patternsz1, patternsz2,
tree_index+1, tree_index+2, trees_in_1, trees_in_2);
if (tree_index + 2 == end_tree)
printf("\nWARNING: extra tree at the end of input tree file.\n");
}
break;
case ALL_IN_FIRST:
/* For every tree, compute the distance between it and every
other tree in that file. */
end_tree = trees_in_1;
if ( output_scheme != FULL_MATRIX ) {
/* verbose or sparse output */
for (index1 = 0 ; index1 < end_tree ; index1++) {
assign_tree (treeA, pattern_array, index1, &patternsz1);
assign_lengths(&length1, pattern_array, index1);
for (index2 = 0 ; index2 < end_tree ; index2++) {
assign_tree (treeB, pattern_array, index2, &patternsz2);
assign_lengths(&length2, pattern_array, index2);
tree_diff (treeA, treeB, length1, length2, patternsz1, patternsz2,
index1 + 1, index2 + 1, trees_in_1, trees_in_2);
}
}
}
else {
/* full matrix output */
for ( index3 = 0 ; index3 < trees_in_1 ; index3 += num_columns) {
for ( index1 = 0 ; index1 < trees_in_1 ; index1++) {
assign_tree (treeA, pattern_array, index1, &patternsz1);
assign_lengths(&length1, pattern_array, index1);
for ( index2 = index3 ;
index2 < index3 + num_columns && index2 < trees_in_1 ;
index2++) {
assign_tree (treeB, pattern_array, index2, &patternsz2);
assign_lengths(&length2, pattern_array, index2);
tree_diff (treeA, treeB, length1, length2, patternsz1, patternsz2,
index1 + 1, index2 + 1, trees_in_1, trees_in_2);
}
}
}
}
break;
case CORR_IN_1_AND_2:
if (trees_in_1 != trees_in_2) {
/* Set end tree to the smaller of the two totals. */
end_tree = trees_in_1 > trees_in_2 ? trees_in_2 : trees_in_1;
/* Print something out to the outfile and to the terminal. */
fprintf(outfile,
"\n\n"
"*** Warning: differing number of trees in first and second\n"
"*** tree files. Only computing %ld pairs.\n"
"\n",
end_tree
);
printf(
"\n"
" *** Warning: differing number of trees in first and second\n"
" *** tree files. Only computing %ld pairs.\n"
"\n",
end_tree
);
}
else
end_tree = trees_in_1;
for (tree_index = 0 ; tree_index < end_tree ; tree_index++) {
/* For every tree, compute the distance between it and the
tree at the parallel location in the other file; do this in
both directions */
assign_tree (treeA, pattern_array, tree_index, &patternsz1);
assign_lengths(&length1, pattern_array, tree_index);
/* (tree_index + trees_in_1) will be the corresponding tree in
the second file. */
assign_tree (treeB, pattern_array, tree_index + trees_in_1, &patternsz2);
assign_lengths(&length2, pattern_array, tree_index + trees_in_1);
tree_diff (treeA, treeB, length1, length2, patternsz1, patternsz2,
tree_index + 1, 0, trees_in_1, trees_in_2);
}
break;
case ALL_IN_1_AND_2:
end_tree = trees_in_1 + trees_in_2;
if ( output_scheme != FULL_MATRIX ) {
for (tree_index = 0 ; tree_index < trees_in_1 ; tree_index++) {
/* For every tree in the first file, compute the distance
between it and every tree in the second file. */
assign_tree (treeA, pattern_array, tree_index, &patternsz1);
assign_lengths(&length1, pattern_array, tree_index);
for (index2 = trees_in_1 ; index2 < end_tree ; index2++) {
assign_tree (treeB, pattern_array, index2, &patternsz2);
assign_lengths(&length2, pattern_array, index2);
tree_diff(treeA, treeB, length1, length2, patternsz1, patternsz2,
tree_index + 1 , index2 + 1, trees_in_1, trees_in_2);
}
}
for ( ; tree_index < end_tree ; tree_index++) {
/* For every tree in the second file, compute the distance
between it and every tree in the first file. */
assign_tree (treeA, pattern_array, tree_index, &patternsz1);
assign_lengths(&length1, pattern_array, tree_index);
for (index2 = 0 ; index2 < trees_in_1 ; index2++) {
assign_tree (treeB, pattern_array, index2, &patternsz2);
assign_lengths(&length2, pattern_array, index2);
tree_diff (treeA, treeB, length1, length2 , patternsz1, patternsz2,
tree_index + 1, index2 + 1, trees_in_1, trees_in_2);
}
}
} else {
for ( index3 = trees_in_1 ; index3 < end_tree ; index3 += num_columns) {
for ( index1 = 0 ; index1 < trees_in_1 ; index1++) {
assign_tree (treeA, pattern_array, index1, &patternsz1);
assign_lengths(&length1, pattern_array, index1);
for ( index2 = index3 ;
index2 < index3 + num_columns && index2 < end_tree ;
index2++) {
assign_tree (treeB, pattern_array, index2, &patternsz2);
assign_lengths(&length2, pattern_array, index2);
tree_diff (treeA, treeB, length1, length2, patternsz1, patternsz2,
index1 + 1, index2 - trees_in_1 + 1, trees_in_1, trees_in_2);
}
}
}
}
break;
}
/* Free up treeA and treeB */
free (treeA);
free (treeB);
} /* compute_distances */
void free_patterns(pattern_elm ***pattern_array, long total_trees)
{
long i, j;
/* Free each pattern array, */
for (i=0 ; i < setsz ; i++) {
for (j = 0 ; j < total_trees ; j++) {
free (pattern_array[i][j]->apattern);
free (pattern_array[i][j]->patternsize);
free (pattern_array[i][j]->length);
free (pattern_array[i][j]);
}
free (pattern_array[i]);
}
free (pattern_array);
} /* free_patterns */
void print_header(long trees_in_1, long trees_in_2)
{
/*long end_tree;*/
switch (tree_pairing) {
case ADJACENT_PAIRS:
/*end_tree = trees_in_1 - 1;*/
if (output_scheme == VERBOSE) {
fprintf(outfile,
"\n"
"Tree distance program, version %s\n\n", VERSION);
if (dtype == PHYLIPBSD)
fprintf (outfile,
"Branch score distances between adjacent pairs of trees:\n"
"\n");
else
fprintf (outfile,
"Symmetric differences between adjacent pairs of trees:\n\n");
}
else if ( output_scheme != SPARSE)
printf ("Error -- cannot output adjacent pairs into a full matrix.\n");
break;
case ALL_IN_FIRST:
/*end_tree = trees_in_1;*/
if (output_scheme == VERBOSE) {
fprintf(outfile, "\nTree distance program, version %s\n\n", VERSION);
if (dtype == PHYLIPBSD)
fprintf (outfile,
"Branch score distances between all pairs of trees in tree file\n\n");
else
fprintf (outfile,
"Symmetric differences between all pairs of trees in tree file:\n\n");
}
else if (output_scheme == FULL_MATRIX) {
fprintf(outfile, "\nTree distance program, version %s\n\n", VERSION);
if (dtype == PHYLIPBSD)
fprintf (outfile,
"Branch score distances between all pairs of trees in tree file:\n\n");
else
fprintf (outfile,
"Symmetric differences between all pairs of trees in tree file:\n\n");
}
break;
case CORR_IN_1_AND_2:
if (output_scheme == VERBOSE) {
fprintf(outfile, "\nTree distance program, version %s\n\n", VERSION);
if (dtype == PHYLIPBSD) {
fprintf (outfile,
"Branch score distances between corresponding pairs of trees\n");
fprintf (outfile, " from first and second tree files:\n\n");
}
else {
fprintf (outfile,
"Symmetric differences between corresponding pairs of trees\n");
fprintf (outfile, " from first and second tree files:\n\n");
}
}
else if (output_scheme != SPARSE)
printf (
"Error -- cannot output corresponding pairs into a full matrix.\n");
break;
case (ALL_IN_1_AND_2) :
if ( output_scheme == VERBOSE) {
fprintf(outfile, "\nTree distance program, version %s\n\n", VERSION);
if (dtype == PHYLIPBSD) {
fprintf (outfile,
"Branch score distances between all pairs of trees\n");
fprintf (outfile, " from first and second tree files:\n\n");
}
else {
fprintf(outfile,"Symmetric differences between all pairs of trees\n");
fprintf(outfile," from first and second tree files:\n\n");
}
} else if ( output_scheme == FULL_MATRIX) {
fprintf(outfile, "\nTree distance program, version %s\n\n", VERSION);
}
break;
}
} /* print_header */
void output_submenu()
{
/* this allows the user to select a different output of distances scheme. */
long loopcount;
boolean done = false;
Char ch;
if (tree_pairing == NO_PAIRING)
return;
loopcount = 0;
while (!done) {
printf ("\nDistances output options:\n");
if ((tree_pairing == ALL_IN_1_AND_2) ||
(tree_pairing == ALL_IN_FIRST))
printf (" F Full matrix.\n");
printf (" V One pair per line, verbose.\n");
printf (" S One pair per line, sparse.\n");
if ((tree_pairing == ALL_IN_1_AND_2) ||
(tree_pairing == ALL_IN_FIRST))
printf ("\n Choose one: (F,V,S)\n");
else
printf ("\n Choose one: (V,S)\n");
fflush(stdout);
scanf("%c%*[^\n]", &ch);
getchar();
uppercase(&ch);
if (strchr("FVS", ch) != NULL) {
switch (ch) {
case 'F':
if ((tree_pairing == ALL_IN_1_AND_2) ||
(tree_pairing == ALL_IN_FIRST))
output_scheme = FULL_MATRIX;
else
/* If this can't be a full matrix... */
continue;
break;
case 'V':
output_scheme = VERBOSE;
break;
case 'S':
output_scheme = SPARSE;
break;
}
done = true;
}
countup(&loopcount, 10);
}
} /* output_submenu */
void pairing_submenu()
{
/* this allows the user to select a different tree pairing scheme. */
long loopcount;
boolean done = false;
Char ch;
loopcount = 0;
while (!done) {
cleerhome();
printf ("Tree Pairing Submenu:\n");
printf (" A Distances between adjacent pairs in tree file.\n");
printf (" P Distances between all possible pairs in tree file.\n");
printf (" C Distances between corresponding pairs in one tree file and another.\n");
printf (" L Distances between all pairs in one tree file and another.\n");
printf ("\n Choose one: (A,P,C,L)\n");
fflush(stdout);
scanf("%c%*[^\n]", &ch);
getchar();
uppercase(&ch);
if (strchr("APCL", ch) != NULL) {
switch (ch) {
case 'A':
tree_pairing = ADJACENT_PAIRS;
break;
case 'P':
tree_pairing = ALL_IN_FIRST;
break;
case 'C':
tree_pairing = CORR_IN_1_AND_2;
break;
case 'L':
tree_pairing = ALL_IN_1_AND_2;
break;
}
output_submenu();
done = true;
}
countup(&loopcount, 10);
}
} /* pairing_submenu */
void read_second_file(pattern_elm ***pattern_array,
long trees_in_1, long trees_in_2,
AjPPhyloTree* treesource)
{
boolean firsttree2, haslengths;
long nextnode, trees_read=0;
long j;
int itree=0;
char *treestr;
firsttree2 = false;
while (treesource[itree]) {
goteof = false;
nextnode = 0;
haslengths = false;
treestr = ajStrGetuniquePtr(&treesource[itree++]->Tree);
allocate_nodep(&nodep, treestr, &spp);
treeread(&treestr, &root, treenode, &goteof, &firsttree2,
nodep, &nextnode, &haslengths,
&grbg, initconsnode, false, -1);
missingname(root);
reordertips();
if (goteof)
continue;
ntrees += trweight;
if (noroot) {
reroot(nodep[outgrno - 1], &nextnode);
didreroot = outgropt;
}
accumulate(root);
gdispose(root);
for (j = 0; j < 2*(1 + spp); j++)
nodep[j] = NULL;
free(nodep);
store_pattern (pattern_array,
trees_in_1 + trees_read);
trees_read++;
}
} /* read_second_file */
void emboss_getoptions(char *pgm, int argc, char *argv[])
{
AjPStr disttype = NULL;
AjPStr tree_p = NULL;
AjPStr style = NULL;
dtype = PHYLIPBSD;
tree_pairing = ADJACENT_PAIRS;
output_scheme = VERBOSE;
ibmpc = IBMCRT;
ansi = ANSICRT;
didreroot = false;
spp = 0;
grbg = NULL;
col = 0;
noroot = true;
numopts = 0;
outgrno = 1;
outgropt = false;
progress = true;
/* The following are not used by treedist, but may be used
in functions in cons.c, so we set them here. */
treeprint = false;
trout = false;
prntsets = false;
embInitPV(pgm, argc, argv, "PHYLIPNEW",VERSION);
phylotrees = ajAcdGetTree("intreefile");
trees_in_1 = 0;
while (phylotrees[trees_in_1]) trees_in_1++;
phylomoretrees = ajAcdGetTree("bintreefile");
trees_in_2 = 0;
while (phylomoretrees[trees_in_2]) trees_in_2++;
progress = ajAcdGetBoolean("progress");
outgrno = ajAcdGetInt("outgrno");
if(outgrno != 0) outgropt = true;
else outgrno = 1;
disttype = ajAcdGetListSingle("dtype");
if(ajStrMatchC(disttype, "s")) dtype = PHYLIPSYMMETRIC;
else dtype = PHYLIPBSD;
noroot = !ajAcdGetBoolean("noroot");
tree_p = ajAcdGetListSingle("pairing");
if(ajStrMatchC(tree_p, "c")) tree_pairing = CORR_IN_1_AND_2;
else if(ajStrMatchC(tree_p, "l")) tree_pairing = ALL_IN_1_AND_2;
style = ajAcdGetListSingle("style");
if(ajStrMatchC(style, "f")) output_scheme = FULL_MATRIX;
else if(ajStrMatchC(style, "s")) output_scheme = SPARSE;
else if(ajStrMatchC(style, "v")) output_scheme = VERBOSE;
embossoutfile = ajAcdGetOutfile("outfile");
emboss_openfile(embossoutfile, &outfile, &outfilename);
} /* embosss_getoptions */
int main(int argc, Char *argv[])
{
pattern_elm ***pattern_array;
long tip_count = 0;
double ln_maxgrp;
double ln_maxgrp1;
double ln_maxgrp2;
node * p;
#ifdef MAC
argc = 1; /* macsetup("Treedist", ""); */
argv[0] = "Treedist";
#endif
init(argc, argv);
emboss_getoptions("ftreedistpair",argc,argv);
/* Initialize option-based variables, then ask for changes regarding
their values. */
ntrees = 0.0;
lasti = -1;
/* read files to determine size of structures we'll be working with */
countcomma(ajStrGetuniquePtr(&phylotrees[0]->Tree),&tip_count);
tip_count++; /* countcomma does a raw comma count, tips is one greater */
/*
* EWFIX.BUG.756 -- this section may be killed if a good solution
* to bug 756 is found
*
* inside cons.c there are several arrays which are allocated
* to size "maxgrp", the maximum number of groups (sets of
* tips more closely connected than the rest of the tree) we
* can see as the code executes.
*
* We have two measures we use to determine how much space to
* allot:
* (1) based on the tip count of the trees in the infile
* (2) based on total number of trees in infile, and
*
* (1) -- Tip Count Method
* Since each group is a subset of the set of tips we must
* represent at most pow(2,tips) different groups. (Technically
* two fewer since we don't store the empty or complete subsets,
* but let's keep this simple.
*
* (2) -- Total Tree Size Method
* Each tree we read results in
* singleton groups for each tip, plus
* a group for each interior node except the root
* Since the singleton tips are identical for each tree, this gives
* a bound of #tips + ( #trees * (# tips - 2 ) )
*
*
* Ignoring small terms where expedient, either of the following should
* result in an adequate allocation:
* pow(2,#tips)
* (#trees + 1) * #tips
*
* Since "maxgrp" is a limit on the number of items we'll need to put
* in a hash, we double it to make space for quick hashing
*
* BUT -- all of this has the possibility for overflow, so -- let's
* make the initial calculations with doubles and then convert
*
*/
/* limit chosen to make hash arithmetic work */
maxgrp = LONG_MAX / 2;
ln_maxgrp = log((double)maxgrp);
/* 2 * (#trees + 1) * #tips */
ln_maxgrp1 = log(2.0 * (double)tip_count *
((double)trees_in_1 + (double)trees_in_2));
/* ln only for 2 * pow(2,#tips) */
ln_maxgrp2 = (double)(1 + tip_count) * log(2.0);
/* now -- find the smallest of the three */
if(ln_maxgrp1 < ln_maxgrp)
{
maxgrp = 2 * (trees_in_1 + trees_in_2 + 1) * tip_count;
ln_maxgrp = ln_maxgrp1;
}
if(ln_maxgrp2 < ln_maxgrp)
{
maxgrp = pow(2,tip_count+1);
}
/* Read the (first) tree file and put together grouping, order, and
timesseen */
read_groups (&pattern_array, trees_in_1 + trees_in_2, tip_count, phylotrees);
if ((tree_pairing == ADJACENT_PAIRS) ||
(tree_pairing == ALL_IN_FIRST)) {
/* Here deal with the adjacent or all-in-first pairing
difference computation */
compute_distances (pattern_array, trees_in_1, 0);
} else if ((tree_pairing == CORR_IN_1_AND_2) ||
(tree_pairing == ALL_IN_1_AND_2)) {
/* Here, open the other tree file, parse it, and then put
together the difference array */
read_second_file (pattern_array, trees_in_1, trees_in_2, phylomoretrees);
compute_distances (pattern_array, trees_in_1, trees_in_2);
} else if (tree_pairing == NO_PAIRING) {
/* Compute the consensus tree. */
putc('\n', outfile);
/* consensus(); Reserved for future development */
}
if (progress)
printf("\nOutput written to file \"%s\"\n\n", outfilename);
FClose(outtree);
FClose(intree);
FClose(outfile);
if ((tree_pairing == ALL_IN_1_AND_2) ||
(tree_pairing == CORR_IN_1_AND_2))
FClose(intree2);
#ifdef MAC
fixmacfile(outfilename);
fixmacfile(outtreename);
#endif
free_patterns (pattern_array, trees_in_1 + trees_in_2);
clean_up_final();
/* clean up grbg */
p = grbg;
while (p != NULL) {
node * r = p;
p = p->next;
free(r->nodeset);
free(r->view);
free(r);
}
printf("Done.\n\n");
embExit();
return 0;
} /* main */
PHYLIPNEW-3.69.650/src/contml.c 0000664 0001750 0001750 00000107612 11305225544 012525 0000000 0000000 /* version 3.6. (c) Copyright 1993-2004 by the University of Washington.
Written by Joseph Felsenstein, Akiko Fuseki, Sean Lamont, and Andrew Keeffe.
Permission is granted to copy and use this program provided no fee is
charged for it and provided that this copyright notice is not removed. */
#include
#include "phylip.h"
#include "cont.h"
#define epsilon1 0.000001 /* small number */
#define epsilon2 0.02 /* not such a small number */
#define smoothings 4 /* number of passes through smoothing algorithm */
#define maxtrees 10 /* maximum number of user trees in KHT test */
#define over 60
AjPPhyloFreq phylofreq;
AjPPhyloTree* phylotrees;
#ifndef OLDC
/* function prototypes */
//void getoptions(void);
void emboss_getoptions(char *pgm, int argc, char *argv[]);
void allocrest(void);
void doinit(void);
void getalleles(void);
void inputdata(void);
void transformgfs(void);
void getinput(void);
void sumlikely(node *, node *, double *);
double evaluate(tree *);
double distance(node *, node *);
void makedists(node *);
void makebigv(node *, boolean *);
void correctv(node *);
void littlev(node *);
void nuview(node *);
void update(node *);
void smooth(node *);
void insert_(node *, node *);
void copynode(node *, node *);
void copy_(tree *, tree *);
void inittip(long, tree *);
void buildnewtip(long, tree *, long);
void buildsimpletree(tree *);
void addtraverse(node *, node *, boolean);
void re_move(node **, node **);
void rearrange(node *);
void coordinates(node *, double, long *, double *);
void drawline(long, double);
void printree(void);
void treeout(node *);
void describe(node *, double, double);
void summarize(void);
void nodeinit(node *);
void initrav(node *);
void treevaluate(void);
void maketree(void);
void globrearrange(void);
/* function prototypes */
#endif
const char* outfilename;
const char* outtreename;
AjPFile embossoutfile;
AjPFile embossouttree;
long nonodes2, loci, totalleles, df, outgrno, col,
datasets, ith, njumble, jumb=0;
long inseed, inseed0;
long *alleles, *locus, *weight;
phenotype3 *x;
boolean all, contchars, global, jumble, lengths, outgropt, trout,
usertree, printdata, progress, treeprint, mulsets, firstset;
longer seed;
long *enterorder;
tree curtree, priortree, bestree, bestree2;
long nextsp, numtrees, which, maxwhich, shimotrees;
/* From maketree, propagated to global */
boolean succeeded;
double maxlogl;
double l0gl[MAXSHIMOTREES];
double *pbar, *sqrtp, *l0gf[MAXSHIMOTREES];
Char ch;
char *progname;
double trweight; /* added to make treeread happy */
boolean goteof;
boolean haslengths; /* end of ones added to make treeread happy */
node *addwhere;
void emboss_getoptions(char *pgm, int argc, char *argv[])
{
AjPStr datatype = NULL;
global = false;
jumble = false;
njumble = 1;
lengths = false;
outgrno = 1;
outgropt = false;
all = true;
contchars = false;
trout = true;
usertree = false;
printdata = false;
progress = true;
treeprint = true;
mulsets = false;
datasets = 1;
embInitPV (pgm, argc, argv, "PHYLIPNEW",VERSION);
phylofreq = ajAcdGetFrequencies("infile");
phylotrees = ajAcdGetTree("intreefile");
if (phylotrees)
{
numtrees = 0;
while (phylotrees[numtrees])
numtrees++;
usertree = true;
lengths = ajAcdGetBoolean("lengths");
}
datatype = ajAcdGetListSingle("datatype");
if(ajStrMatchC(datatype, "c")) contchars = true;
outgrno = ajAcdGetInt("outgrno");
if(outgrno != 0) outgropt = true;
else outgrno = 1;
if(!usertree) {
global = ajAcdGetBoolean("global");
njumble = ajAcdGetInt("njumble");
if(njumble >0) {
inseed = ajAcdGetInt("seed");
jumble = true;
emboss_initseed(inseed, &inseed0, seed);
}
else njumble = 1;
}
printdata = ajAcdGetBoolean("printdata");
progress = ajAcdGetBoolean("progress");
treeprint = ajAcdGetBoolean("treeprint");
trout = ajAcdGetToggle("trout");
embossoutfile = ajAcdGetOutfile("outfile");
embossouttree = ajAcdGetOutfile("outtreefile");
emboss_openfile(embossoutfile, &outfile, &outfilename);
if(trout) emboss_openfile(embossouttree, &outtree, &outtreename);
fprintf(outfile, "\nContinuous character Maximum Likelihood");
fprintf(outfile, " method version %s\n\n",VERSION);
ajStrDel(&datatype);
} /* emboss_getoptions */
void allocrest()
{ /* allocate arrays for number of alleles, the data coordinates, names etc */
alleles = (long *)Malloc(loci*sizeof(long));
if (contchars)
locus = (long *)Malloc(loci*sizeof(long));
x = (phenotype3 *)Malloc(spp*sizeof(phenotype3));
nayme = (naym *)Malloc(spp*sizeof(naym));
enterorder = (long *)Malloc(spp*sizeof(long));
} /* allocrest */
void doinit()
{ /* initializes variables */
inputnumbersfreq(phylofreq, &spp, &loci, &nonodes2, 2);
if (printdata)
fprintf(outfile, "\n%4ld Populations, %4ld Loci\n", spp, loci);
alloctree(&curtree.nodep, nonodes2);
if (!usertree) {
alloctree(&bestree.nodep, nonodes2);
alloctree(&priortree.nodep, nonodes2);
if (njumble > 1) {
alloctree(&bestree2.nodep, nonodes2);
}
}
allocrest();
} /* doinit */
void getalleles()
{ /* set up number of alleles at loci */
long i, j, m;
if (!firstset)
samenumspfreq(phylofreq, &loci, ith);
if (contchars ) {
totalleles = loci;
for (i = 1; i <= loci; i++) {
locus[i - 1] = i;
alleles[i - 1] = 1;
}
df = loci;
} else {
totalleles = 0;
if (printdata) {
fprintf(outfile, "\nNumbers of alleles at the loci:\n");
fprintf(outfile, "------- -- ------- -- --- -----\n\n");
}
for (i = 1; i <= loci; i++) {
alleles[i-1] = phylofreq->Allele[i-1];
if (alleles[i - 1] <= 0) {
printf("ERROR: Bad number of alleles: %ld at locus %ld\n", alleles[i-1], i);
exxit(-1);
}
totalleles += alleles[i - 1];
if (printdata)
fprintf(outfile, "%4ld", alleles[i - 1]);
}
locus = (long *)Malloc(totalleles*sizeof(long));
m = 0;
for (i = 1; i <= loci; i++) {
for (j = 0; j < alleles[i - 1]; j++)
locus[m+j] = i;
m += alleles[i - 1];
}
df = totalleles - loci;
}
allocview(&curtree, nonodes2, totalleles);
if (!usertree) {
allocview(&bestree, nonodes2, totalleles);
allocview(&priortree, nonodes2, totalleles);
if (njumble > 1)
allocview(&bestree2, nonodes2, totalleles);
}
for (i = 0; i < spp; i++)
x[i] = (phenotype3)Malloc(totalleles*sizeof(double));
pbar = (double *)Malloc(totalleles*sizeof(double));
if (usertree)
for (i = 0; i < MAXSHIMOTREES; i++)
l0gf[i] = (double *)Malloc(totalleles*sizeof(double));
if (printdata)
putc('\n', outfile);
} /* getalleles */
void inputdata()
{ /* read species data */
long i, j, k, l, m, m0, n, p;
double sum;
ajint ipos = 0;
if (printdata) {
fprintf(outfile, "\nName");
if (contchars)
fprintf(outfile, " Phenotypes\n");
else
fprintf(outfile, " Gene Frequencies\n");
fprintf(outfile, "----");
if (contchars)
fprintf(outfile, " ----------\n");
else
fprintf(outfile, " ---- -----------\n");
putc('\n', outfile);
if (!contchars) {
for (j = 1; j <= nmlngth - 8; j++)
putc(' ', outfile);
fprintf(outfile, "locus:");
p = 1;
for (j = 1; j <= loci; j++) {
if (all)
n = alleles[j - 1];
else
n = alleles[j - 1] - 1;
for (k = 1; k <= n; k++) {
fprintf(outfile, "%10ld", j);
if (p % 6 == 0 && (all || p < df)) {
putc('\n', outfile);
for (l = 1; l <= nmlngth - 2; l++)
putc(' ', outfile);
}
p++;
}
}
fprintf(outfile, "\n\n");
}
}
for (i = 0; i < spp; i++) {
initnamefreq(phylofreq, i);
if (printdata)
for (j = 0; j < nmlngth; j++)
putc(nayme[i][j], outfile);
m = 1;
p = 1;
for (j = 1; j <= loci; j++) {
m0 = m;
sum = 0.0;
if (contchars)
n = 1;
else if (all)
n = alleles[j - 1];
else
n = alleles[j - 1] - 1;
for (k = 1; k <= n; k++) {
x[i][m - 1] = phylofreq->Data[ipos++];
sum += x[i][m - 1];
if (!contchars && x[i][m - 1] < 0.0) {
printf("\n\nERROR: locus %ld in species %ld: an allele", j, i+1);
printf(" frequency is negative\n");
exxit(-1);
}
if (printdata) {
fprintf(outfile, "%10.5f", x[i][m - 1]);
if (p % 6 == 0 && (all || p < df)) {
putc('\n', outfile);
for (l = 1; l <= nmlngth; l++)
putc(' ', outfile);
}
}
p++;
m++;
}
if (all && !contchars) {
if (fabs(sum - 1.0) > epsilon2) {
printf(
"\n\nERROR: Locus %ld in species %ld: frequencies do not add up to 1\n",
j, i + 1);
printf("\nFrequencies are:\n");
for (l = m0; l <= m-3; l++)
printf("%f+", x[i][l]);
printf("%f = %f\n\n", x[i][m-2], sum);
exxit(-1);
} else {
for (l = 0; l <= m-2; l++)
x[i][l] /= sum;
}
}
if (!all && !contchars) {
x[i][m-1] = 1.0 - sum;
if (x[i][m-1] < 0.0) {
if (x[i][m-1] > -epsilon2) {
for (l = 0; l <= m-2; l++)
x[i][l] /= sum;
x[i][m-1] = 0.0;
} else {
printf("\n\nERROR: Locus %ld in species %ld: ", j, i + 1);
printf("frequencies add up to more than 1\n");
printf("\nFrequencies are:\n");
for (l = m0-1; l <= m-3; l++)
printf("%f+", x[i][l]);
printf("%f = %f\n\n", x[i][m-2], sum);
exxit(-1);
}
}
m++;
}
}
if (printdata)
putc('\n', outfile);
}
if (printdata)
putc('\n', outfile);
} /* inputdata */
void transformgfs()
{ /* do stereographic projection transformation on gene frequencies to
get variables that come closer to independent Brownian motions */
long i, j, k, l, m, n, maxalleles;
double f, sum;
double *sumprod, *sqrtp, *pbar;
phenotype3 *c;
sumprod = (double *)Malloc(loci*sizeof(double));
sqrtp = (double *)Malloc(totalleles*sizeof(double));
pbar = (double *)Malloc(totalleles*sizeof(double));
for (i = 0; i < totalleles; i++) { /* get mean gene frequencies */
pbar[i] = 0.0;
for (j = 0; j < spp; j++)
pbar[i] += x[j][i];
pbar[i] /= spp;
if (pbar[i] == 0.0)
sqrtp[i] = 0.0;
else
sqrtp[i] = sqrt(pbar[i]);
}
for (i = 0; i < spp; i++) {
for (j = 0; j < loci; j++) /* for each locus, sum of root(p*x) */
sumprod[j] = 0.0;
for (j = 0; j < totalleles; j++)
if ((pbar[j]*x[i][j]) >= 0.0)
sumprod[locus[j]-1] += sqrtp[j]*sqrt(x[i][j]);
for (j = 0; j < totalleles; j++) { /* the projection to tangent plane */
f = (1.0 + sumprod[locus[j]-1])/2.0;
if (x[i][j] == 0.0)
x[i][j] = (2.0/f - 1.0)*sqrtp[j];
else
x[i][j] = (1.0/f)*sqrt(x[i][j]) + (1.0/f - 1.0)*sqrtp[j];
}
}
maxalleles = 0;
for (i = 0; i < loci; i++)
if (alleles[i] > maxalleles)
maxalleles = alleles[i];
c = (phenotype3 *)Malloc(maxalleles*sizeof(phenotype3));
for (i = 0; i < maxalleles; i++) /* enough room for any locus's contrasts */
c[i] = (double *)Malloc(maxalleles*sizeof(double));
m = 0;
for (j = 0; j < loci; j++) { /* do this for each locus */
for (k = 0; k < alleles[j]-1; k++) { /* one fewer than # of alleles */
c[k][0] = 1.0;
for (l = 0; l < k; l++) { /* for alleles 2 to k make it ... */
sum = 0.0;
for (n = 0; n <= l; n++)
sum += c[k][n]*c[l][n];
if (fabs(c[l][l+1]) > 0.000000001) /* ... orthogonal to those ones */
c[k][l+1] = -sum / c[l][l+1]; /* set coeff to make orthogonal */
else
c[k][l+1] = 1.0;
}
sum = 0.0;
for (l = 0; l <= k; l++) /* make it orthogonal to vector of sqrtp's */
sum += c[k][l]*sqrtp[m+l];
if (sqrtp[m+k+1] > 0.0000000001)
c[k][k+1] = - sum / sqrtp[m+k+1];
else {
for (l = 0; l <= k; l++)
c[k][l] = 0.0;
c[k][k+1] = 1.0;
}
sum = 0.0;
for (l = 0; l <= k+1; l++)
sum += c[k][l]*c[k][l];
sum = sqrt(sum);
for (l = 0; l <= k+1; l++)
if (sum > 0.0000000001)
c[k][l] /= sum;
}
for (i = 0; i < spp; i++) { /* the orthonormal axes in the plane */
for (l = 0; l < alleles[k]-1; l++) { /* compute the l-th one */
c[maxalleles-1][l] = 0.0; /* temporarily store it ... */
for (n = 0; n <= l+1; n++)
c[maxalleles-1][l] += c[l][n]*x[i][m+n];
}
for (l = 0; l < alleles[k]-1; l++)
x[i][m+l] = c[maxalleles-1][l]; /* replace the gene freqs by it */
}
m += alleles[j];
}
for (i = 0; i < maxalleles; i++)
free(c[i]);
free(c);
free(sumprod);
free(sqrtp);
free(pbar);
} /* transformgfs */
void getinput()
{ /* reads the input data */
getalleles();
inputdata();
if (!contchars) {
transformgfs();
}
} /* getinput */
void sumlikely(node *p, node *q, double *sum)
{ /* sum contribution to likelihood over forks in tree */
long i, j, m;
double term, sumsq, vee;
double temp;
if (!p->tip)
sumlikely(p->next->back, p->next->next->back, sum);
if (!q->tip)
sumlikely(q->next->back, q->next->next->back, sum);
if (p->back == q)
vee = p->v;
else
vee = p->v + q->v;
vee += p->deltav + q->deltav;
if (vee <= 1.0e-10) {
printf("ERROR: check for two identical species ");
printf("and eliminate one from the data\n");
exxit(-1);
}
sumsq = 0.0;
if (usertree && which <= MAXSHIMOTREES) {
for (i = 0; i < loci; i++)
l0gf[which - 1][i] += (1 - alleles[i]) * log(vee) / 2.0;
}
if (contchars) {
m = 0;
for (i = 0; i < loci; i++) {
temp = p->view[i] - q->view[i];
term = temp * temp;
if (usertree && which <= MAXSHIMOTREES)
l0gf[which - 1][i] -= term / (2.0 * vee);
sumsq += term;
}
} else {
m = 0;
for (i = 0; i < loci; i++) {
for (j = 1; j < alleles[i]; j++) {
temp = p->view[m+j-1] - q->view[m+j-1];
term = temp * temp;
if (usertree && which <= MAXSHIMOTREES)
l0gf[which - 1][i] -= term / (2.0 * vee);
sumsq += term;
}
m += alleles[i];
}
}
(*sum) += df * log(vee) / -2.0 - sumsq / (2.0 * vee);
} /* sumlikely */
double evaluate(tree *t)
{ /* evaluate likelihood of a tree */
long i;
double sum;
sum = 0.0;
if (usertree && which <= MAXSHIMOTREES) {
for (i = 0; i < loci; i++)
l0gf[which - 1][i] = 0.0;
}
sumlikely(t->start->back, t->start, &sum);
if (usertree && which <= MAXSHIMOTREES) {
l0gl[which - 1] = sum;
if (which == 1) {
maxwhich = 1;
maxlogl = sum;
} else if (sum > maxlogl) {
maxwhich = which;
maxlogl = sum;
}
}
t->likelihood = sum;
return sum;
} /* evaluate */
double distance(node *p, node *q)
{ /* distance between two nodes */
long i, j, m;
double sum, temp;
sum = 0.0;
if (!contchars) {
m = 0;
for (i = 0; i < loci; i++) {
for (j = 0; j < alleles[i]-1; j++) {
temp = p->view[m+j] - q->view[m+j];
sum += temp * temp;
}
m += alleles[i];
}
}
else {
for (i = 0; i < totalleles; i++) {
temp = p->view[i] - q->view[i];
sum += temp * temp;
}
}
return sum;
} /* distance */
void makedists(node *p)
{ /* compute distances among three neighbors of a node */
long i;
node *q;
for (i = 1; i <= 3; i++) {
q = p->next;
p->dist = distance(p->back, q->back);
p = q;
}
} /* makedists */
void makebigv(node *p, boolean *negatives)
{ /* make new branch length */
long i;
node *temp, *q, *r;
q = p->next;
r = q->next;
*negatives = false;
for (i = 1; i <= 3; i++) {
p->bigv = p->v + p->back->deltav;
if (p->iter) {
p->bigv = (p->dist + r->dist - q->dist) / (df * 2);
p->back->bigv = p->bigv;
if (p->bigv < p->back->deltav)
*negatives = true;
}
temp = p;
p = q;
q = r;
r = temp;
}
} /* makebigv */
void correctv(node *p)
{ /* iterate branch lengths if some are to be zero */
node *q, *r, *temp;
long i, j;
double f1, f2, vtot;
q = p->next;
r = q->next;
for (i = 1; i <= smoothings; i++) {
for (j = 1; j <= 3; j++) {
vtot = q->bigv + r->bigv;
if (vtot > 0.0)
f1 = q->bigv / vtot;
else
f1 = 0.5;
f2 = 1.0 - f1;
p->bigv = (f1 * r->dist + f2 * p->dist - f1 * f2 * q->dist) / df;
p->bigv -= vtot * f1 * f2;
if (p->bigv < p->back->deltav)
p->bigv = p->back->deltav;
p->back->bigv = p->bigv;
temp = p;
p = q;
q = r;
r = temp;
}
}
} /* correctv */
void littlev(node *p)
{ /* remove part of it that belongs to other barnches */
long i;
for (i = 1; i <= 3; i++) {
if (p->iter)
p->v = p->bigv - p->back->deltav;
if (p->back->iter)
p->back->v = p->v;
p = p->next;
}
} /* littlev */
void nuview(node *p)
{ /* renew information about subtrees */
long i, j, k, m;
node *q, *r, *a, *b, *temp;
double v1, v2, vtot, f1, f2;
q = p->next;
r = q->next;
for (i = 1; i <= 3; i++) {
a = q->back;
b = r->back;
v1 = q->bigv;
v2 = r->bigv;
vtot = v1 + v2;
if (vtot > 0.0)
f1 = v2 / vtot;
else
f1 = 0.5;
f2 = 1.0 - f1;
m = 0;
for (j = 0; j < loci; j++) {
for (k = 1; k <= alleles[j]; k++)
p->view[m+k-1] = f1 * a->view[m+k-1] + f2 * b->view[m+k-1];
m += alleles[j];
}
p->deltav = v1 * f1;
temp = p;
p = q;
q = r;
r = temp;
}
} /* nuview */
void update(node *p)
{ /* update branch lengths around a node */
boolean negatives;
if (p->tip)
return;
makedists(p);
makebigv(p,&negatives);
if (negatives)
correctv(p);
littlev(p);
nuview(p);
} /* update */
void smooth(node *p)
{ /* go through tree getting new branch lengths and views */
if (p->tip)
return;
update(p);
smooth(p->next->back);
smooth(p->next->next->back);
} /* smooth */
void insert_(node *p, node *q)
{ /* put p and q together and iterate info. on resulting tree */
long i;
hookup(p->next->next, q->back);
hookup(p->next, q);
for (i = 1; i <= smoothings; i++) {
smooth(p);
smooth(p->back);
}
} /* insert_ */
void copynode(node *c, node *d)
{ /* make a copy of a node */
memcpy(d->view, c->view, totalleles*sizeof(double));
d->v = c->v;
d->iter = c->iter;
d->deltav = c->deltav;
d->bigv = c->bigv;
d->dist = c->dist;
d->xcoord = c->xcoord;
d->ycoord = c->ycoord;
d->ymin = c->ymin;
d->ymax = c->ymax;
} /* copynode */
void copy_(tree *a, tree *b)
{ /* make a copy of tree a to tree b */
long i, j;
node *p, *q;
for (i = 0; i < spp; i++) {
copynode(a->nodep[i], b->nodep[i]);
if (a->nodep[i]->back) {
if (a->nodep[i]->back == a->nodep[a->nodep[i]->back->index - 1])
b->nodep[i]->back = b->nodep[a->nodep[i]->back->index - 1];
else if (a->nodep[i]->back == a->nodep[a->nodep[i]->back->index - 1]->next)
b->nodep[i]->back = b->nodep[a->nodep[i]->back->index - 1]->next;
else
b->nodep[i]->back = b->nodep[a->nodep[i]->back->index - 1]->next->next;
}
else b->nodep[i]->back = NULL;
}
for (i = spp; i < nonodes2; i++) {
p = a->nodep[i];
q = b->nodep[i];
for (j = 1; j <= 3; j++) {
copynode(p, q);
if (p->back) {
if (p->back == a->nodep[p->back->index - 1])
q->back = b->nodep[p->back->index - 1];
else if (p->back == a->nodep[p->back->index - 1]->next)
q->back = b->nodep[p->back->index - 1]->next;
else
q->back = b->nodep[p->back->index - 1]->next->next;
}
else
q->back = NULL;
p = p->next;
q = q->next;
}
}
b->likelihood = a->likelihood;
b->start = a->start;
} /* copy_ */
void inittip(long m, tree *t)
{ /* initialize branch lengths and views in a tip */
node *tmp;
tmp = t->nodep[m - 1];
memcpy(tmp->view, x[m - 1], totalleles*sizeof(double));
tmp->deltav = 0.0;
tmp->v = 0.0;
} /* inittip */
void buildnewtip(long m, tree *t, long nextsp)
{ /* initialize and hook up a new tip */
node *p;
inittip(m, t);
p = t->nodep[nextsp + spp - 3];
hookup(t->nodep[m - 1], p);
} /* buildnewtip */
void buildsimpletree(tree *t)
{ /* make and initialize a three-species tree */
inittip(enterorder[0], t);
inittip(enterorder[1], t);
hookup(t->nodep[enterorder[0] - 1], t->nodep[enterorder[1] - 1]);
buildnewtip(enterorder[2], t, nextsp);
insert_(t->nodep[enterorder[2] - 1]->back, t->nodep[enterorder[0] - 1]);
} /* buildsimpletree */
void addtraverse(node *p, node *q, boolean contin)
{ /* traverse through a tree, finding best place to add p */
insert_(p, q);
numtrees++;
if (evaluate(&curtree) > bestree.likelihood) {
copy_(&curtree, &bestree);
addwhere = q;
}
copy_(&priortree, &curtree);
if (!q->tip && contin) {
addtraverse(p, q->next->back, contin);
addtraverse(p, q->next->next->back, contin);
}
} /* addtraverse */
void re_move(node **p, node **q)
{ /* remove p and record in q where it was */
*q = (*p)->next->back;
hookup(*q, (*p)->next->next->back);
(*p)->next->back = NULL;
(*p)->next->next->back = NULL;
update(*q);
update((*q)->back);
} /* re_move */
void globrearrange()
{ /* does global rearrangements */
tree globtree;
tree oldtree;
int i,j,k,num_sibs,num_sibs2;
node *where,*sib_ptr,*sib_ptr2;
double oldbestyet = curtree.likelihood;
int success = false;
alloctree(&globtree.nodep,nonodes2);
alloctree(&oldtree.nodep,nonodes2);
setuptree(&globtree,nonodes2);
setuptree(&oldtree,nonodes2);
allocview(&oldtree, nonodes2, totalleles);
allocview(&globtree, nonodes2, totalleles);
copy_(&curtree,&globtree);
copy_(&curtree,&oldtree);
for ( i = spp ; i < nonodes2 ; i++ ) {
num_sibs = count_sibs(curtree.nodep[i]);
sib_ptr = curtree.nodep[i];
if ( (i - spp) % (( nonodes2 / 72 ) + 1 ) == 0 )
putchar('.');
fflush(stdout);
for ( j = 0 ; j <= num_sibs ; j++ ) {
re_move(&sib_ptr,&where);
copy_(&curtree,&priortree);
if (where->tip) {
copy_(&oldtree,&curtree);
copy_(&oldtree,&bestree);
sib_ptr = sib_ptr->next;
continue;
}
else num_sibs2 = count_sibs(where);
sib_ptr2 = where;
for ( k = 0 ; k < num_sibs2 ; k++ ) {
addwhere = NULL;
addtraverse(sib_ptr,sib_ptr2->back,true);
if ( addwhere && where != addwhere && where->back != addwhere
&& bestree.likelihood > globtree.likelihood) {
copy_(&bestree,&globtree);
success = true;
}
sib_ptr2 = sib_ptr2->next;
}
copy_(&oldtree,&curtree);
copy_(&oldtree,&bestree);
sib_ptr = sib_ptr->next;
}
}
copy_(&globtree,&curtree);
copy_(&globtree,&bestree);
if (success && globtree.likelihood > oldbestyet) {
succeeded = true;
}
else {
succeeded = false;
}
freeview(&oldtree, nonodes2);
freeview(&globtree, nonodes2);
freetree(&globtree.nodep,nonodes2);
freetree(&oldtree.nodep,nonodes2);
}
void rearrange(node *p)
{ /* rearranges the tree locally */
node *q, *r;
if (!p->tip && !p->back->tip) {
r = p->next->next;
re_move(&r, &q );
copy_(&curtree, &priortree);
addtraverse(r, q->next->back, false);
addtraverse(r, q->next->next->back, false);
copy_(&bestree, &curtree);
}
if (!p->tip) {
rearrange(p->next->back);
rearrange(p->next->next->back);
}
} /* rearrange */
void coordinates(node *p, double lengthsum, long *tipy, double *tipmax)
{ /* establishes coordinates of nodes */
node *q, *first, *last;
if (p->tip) {
p->xcoord = lengthsum;
p->ycoord = *tipy;
p->ymin = *tipy;
p->ymax = *tipy;
(*tipy) += down;
if (lengthsum > (*tipmax))
(*tipmax) = lengthsum;
return;
}
q = p->next;
do {
coordinates(q->back, lengthsum + q->v, tipy,tipmax);
q = q->next;
} while ((p == curtree.start || p != q) &&
(p != curtree.start || p->next != q));
first = p->next->back;
q = p;
while (q->next != p)
q = q->next;
last = q->back;
p->xcoord = lengthsum;
if (p == curtree.start)
p->ycoord = p->next->next->back->ycoord;
else
p->ycoord = (first->ycoord + last->ycoord) / 2;
p->ymin = first->ymin;
p->ymax = last->ymax;
} /* coordinates */
void drawline(long i, double scale)
{ /* draws one row of the tree diagram by moving up tree */
node *p, *q;
long n, j;
boolean extra;
node *r, *first = NULL, *last = NULL;
boolean done;
p = curtree.start;
q = curtree.start;
extra = false;
if (i == (long)p->ycoord && p == curtree.start) {
if (p->index - spp >= 10)
fprintf(outfile, " %2ld", p->index - spp);
else
fprintf(outfile, " %ld", p->index - spp);
extra = true;
} else
fprintf(outfile, " ");
do {
if (!p->tip) {
r = p->next;
done = false;
do {
if (i >= (long)r->back->ymin && i <= (long)r->back->ymax) {
q = r->back;
done = true;
}
r = r->next;
} while (!(done || (p != curtree.start && r == p) ||
(p == curtree.start && r == p->next)));
first = p->next->back;
r = p;
while (r->next != p)
r = r->next;
last = r->back;
if (p == curtree.start)
last = p->back;
}
done = (p->tip || p == q);
n = (long)(scale * (q->xcoord - p->xcoord) + 0.5);
if (n < 3 && !q->tip)
n = 3;
if (extra) {
n--;
extra = false;
}
if ((long)q->ycoord == i && !done) {
if ((long)p->ycoord != (long)q->ycoord)
putc('+', outfile);
else
putc('-', outfile);
if (!q->tip) {
for (j = 1; j <= n - 2; j++)
putc('-', outfile);
if (q->index - spp >= 10)
fprintf(outfile, "%2ld", q->index - spp);
else
fprintf(outfile, "-%ld", q->index - spp);
extra = true;
} else {
for (j = 1; j < n; j++)
putc('-', outfile);
}
} else if (!p->tip) {
if ((long)last->ycoord > i && (long)first->ycoord < i
&& i != (long)p->ycoord) {
putc('!', outfile);
for (j = 1; j < n; j++)
putc(' ', outfile);
} else {
for (j = 1; j <= n; j++)
putc(' ', outfile);
}
} else {
for (j = 1; j <= n; j++)
putc(' ', outfile);
}
if (q != p)
p = q;
} while (!done);
if ((long)p->ycoord == i && p->tip) {
for (j = 0; j < nmlngth; j++)
putc(nayme[p->index - 1][j], outfile);
}
putc('\n', outfile);
} /* drawline */
void printree()
{ /* prints out diagram of the tree */
long i;
long tipy;
double tipmax,scale;
if (!treeprint)
return;
putc('\n', outfile);
tipy = 1;
tipmax = 0.0;
coordinates(curtree.start, 0.0, &tipy,&tipmax);
scale = over / (tipmax + 0.0001);
for (i = 1; i <= (tipy - down); i++)
drawline(i,scale);
putc('\n', outfile);
} /* printree */
void treeout(node *p)
{ /* write out file with representation of final tree */
long i, n, w;
Char c;
double x;
if (p->tip) {
n = 0;
for (i = 1; i <= nmlngth; i++) {
if (nayme[p->index - 1][i - 1] != ' ')
n = i;
}
for (i = 0; i < n; i++) {
c = nayme[p->index - 1][i];
if (c == ' ')
c = '_';
putc(c, outtree);
}
col += n;
} else {
putc('(', outtree);
col++;
treeout(p->next->back);
putc(',', outtree);
col++;
if (col > 55) {
putc('\n', outtree);
col = 0;
}
treeout(p->next->next->back);
if (p == curtree.start) {
putc(',', outtree);
col++;
if (col > 45) {
putc('\n', outtree);
col = 0;
}
treeout(p->back);
}
putc(')', outtree);
col++;
}
x = p->v;
if (x > 0.0)
w = (long)(0.43429448222 * log(x));
else if (x == 0.0)
w = 0;
else
w = (long)(0.43429448222 * log(-x)) + 1;
if (w < 0)
w = 0;
if (p == curtree.start)
fprintf(outtree, ";\n");
else {
fprintf(outtree, ":%*.8f", (int)w + 7, x);
col += w + 8;
}
} /* treeout */
void describe(node *p, double chilow, double chihigh)
{ /* print out information for one branch */
long i;
node *q;
double bigv, delta;
q = p->back;
fprintf(outfile, "%3ld ", q->index - spp);
if (p->tip) {
for (i = 0; i < nmlngth; i++)
putc(nayme[p->index - 1][i], outfile);
} else
fprintf(outfile, "%4ld ", p->index - spp);
fprintf(outfile, "%15.8f", q->v);
delta = p->deltav + p->back->deltav;
bigv = p->v + delta;
if (p->iter)
fprintf(outfile, " (%12.8f,%12.8f)",
chilow * bigv - delta, chihigh * bigv - delta);
fprintf(outfile, "\n");
if (!p->tip) {
describe(p->next->back, chilow,chihigh);
describe(p->next->next->back, chilow,chihigh);
}
} /* describe */
void summarize(void)
{ /* print out branch lengths etc. */
double chilow,chihigh;
fprintf(outfile, "\nremember: ");
if (outgropt)
fprintf(outfile, "(although rooted by outgroup) ");
fprintf(outfile, "this is an unrooted tree!\n\n");
fprintf(outfile, "Ln Likelihood = %11.5f\n", curtree.likelihood);
if (df == 1) {
chilow = 0.000982;
chihigh = 5.02389;
} else if (df == 2) {
chilow = 0.05064;
chihigh = 7.3777;
} else {
chilow = 1.0 - 2.0 / (df * 9);
chihigh = chilow;
chilow -= 1.95996 * sqrt(2.0 / (df * 9));
chihigh += 1.95996 * sqrt(2.0 / (df * 9));
chilow *= chilow * chilow;
chihigh *= chihigh * chihigh;
}
fprintf(outfile, "\nBetween And Length");
fprintf(outfile, " Approx. Confidence Limits\n");
fprintf(outfile, "------- --- ------");
fprintf(outfile, " ------- ---------- ------\n");
describe(curtree.start->next->back, chilow,chihigh);
describe(curtree.start->next->next->back, chilow,chihigh);
describe(curtree.start->back, chilow, chihigh);
fprintf(outfile, "\n\n");
if (trout) {
col = 0;
treeout(curtree.start);
}
} /* summarize */
void nodeinit(node *p)
{ /* initialize a node */
node *q, *r;
long i, j, m;
if (p->tip)
return;
q = p->next->back;
r = p->next->next->back;
nodeinit(q);
nodeinit(r);
m = 0;
for (i = 0; i < loci; i++) {
for (j = 1; j < alleles[i]; j++)
p->view[m+j-1] = 0.5 * q->view[m+j-1] + 0.5 * r->view[m+j-1];
m += alleles[i];
}
if ((!lengths) || p->iter)
p->v = 0.1;
if ((!lengths) || p->back->iter)
p->back->v = 0.1;
} /* nodeinit */
void initrav(node *p)
{ /* traverse to initialize */
node* q;
if (p->tip)
nodeinit(p->back);
else {
q = p->next;
while ( q != p) {
initrav(q->back);
q = q->next;
}
}
} /* initrav */
void treevaluate()
{ /* evaluate user-defined tree, iterating branch lengths */
long i;
initrav(curtree.start);
initrav(curtree.start->back);
for (i = 1; i <= smoothings * 4; i++)
smooth(curtree.start);
evaluate(&curtree);
} /* treevaluate */
void maketree()
{ /* construct the tree */
long i;
char* treestr;
if (usertree) {
if(numtrees > MAXSHIMOTREES)
shimotrees = MAXSHIMOTREES;
else
shimotrees = numtrees;
if (numtrees > 2)
emboss_initseed(inseed, &inseed0, seed);
if (treeprint) {
fprintf(outfile, "User-defined tree");
if (numtrees > 1)
putc('s', outfile);
putc('\n', outfile);
}
setuptree(&curtree, nonodes2);
for (which = 1; which <= spp; which++)
inittip(which, &curtree);
which = 1;
while (which <= numtrees) {
treestr = ajStrGetuniquePtr(&phylotrees[which-1]->Tree);
treeread2 (&treestr, &curtree.start, curtree.nodep,
lengths, &trweight, &goteof, &haslengths, &spp,false,nonodes2);
curtree.start = curtree.nodep[outgrno - 1]->back;
treevaluate();
printree();
summarize();
which++;
}
FClose(intree);
if (numtrees > 1 && loci > 1 ) {
weight = (long *)Malloc(loci*sizeof(long));
for (i = 0; i < loci; i++)
weight[i] = 1;
standev2(numtrees, maxwhich, 0, loci-1, maxlogl, l0gl, l0gf, seed);
free(weight);
fprintf(outfile, "\n\n");
}
} else { /* if ( !usertree ) */
if (jumb == 1) {
setuptree(&curtree, nonodes2);
setuptree(&priortree, nonodes2);
setuptree(&bestree, nonodes2);
if (njumble > 1)
setuptree(&bestree2, nonodes2);
}
for (i = 1; i <= spp; i++)
enterorder[i - 1] = i;
if (jumble)
randumize(seed, enterorder);
nextsp = 3;
buildsimpletree(&curtree);
curtree.start = curtree.nodep[enterorder[0] - 1]->back;
if (jumb == 1) numtrees = 1;
nextsp = 4;
if (progress) {
printf("Adding species:\n");
writename(0, 3, enterorder);
#ifdef WIN32
phyFillScreenColor();
#endif
}
while (nextsp <= spp) {
buildnewtip(enterorder[nextsp - 1], &curtree, nextsp);
copy_(&curtree, &priortree);
bestree.likelihood = -DBL_MAX;
addtraverse(curtree.nodep[enterorder[nextsp - 1] - 1]->back,
curtree.start, true );
copy_(&bestree, &curtree);
if (progress) {
writename(nextsp - 1, 1, enterorder);
#ifdef WIN32
phyFillScreenColor();
#endif
}
if (global && nextsp == spp) {
if (progress) {
printf("\nDoing global rearrangements\n");
printf(" !");
for (i = 1; i <= spp - 2; i++)
if ( (i - spp) % (( nonodes2 / 72 ) + 1 ) == 0 )
putchar('-');
printf("!\n");
printf(" ");
}
}
succeeded = true;
while (succeeded) {
succeeded = false;
if ( global && nextsp == spp )
globrearrange();
else
rearrange(curtree.start);
if (global && nextsp == spp)
putc('\n', outfile);
}
if (global && nextsp == spp && progress)
putchar('\n');
if (njumble > 1) {
if (jumb == 1 && nextsp == spp)
copy_(&bestree, &bestree2);
else if (nextsp == spp) {
if (bestree2.likelihood < bestree.likelihood)
copy_(&bestree, &bestree2);
}
}
if (nextsp == spp && jumb == njumble) {
if (njumble > 1) copy_(&bestree2, &curtree);
curtree.start = curtree.nodep[outgrno - 1]->back;
printree();
summarize();
}
nextsp++;
}
}
if ( jumb < njumble)
return;
if (progress) {
printf("\nOutput written to file \"%s\"\n", outfilename);
if (trout)
printf("\nTree also written onto file \"%s\"\n\n", outtreename);
}
freeview(&curtree, nonodes2);
if (!usertree) {
freeview(&bestree, nonodes2);
freeview(&priortree, nonodes2);
}
for (i = 0; i < spp; i++)
free(x[i]);
if (!contchars) {
free(locus);
free(pbar);
}
} /* maketree */
int main(int argc, Char *argv[])
{ /* main program */
long i;
#ifdef MAC
argc = 1; /* macsetup("Contml",""); */
argv[0] = "Contml";
#endif
init(argc, argv);
emboss_getoptions("fcontml", argc, argv);
progname = argv[0];
ibmpc = IBMCRT;
ansi = ANSICRT;
firstset = true;
doinit();
for (ith = 1; ith <= datasets; ith++) {
getinput();
if (ith == 1)
firstset = false;
if (datasets > 1) {
fprintf(outfile, "Data set # %ld:\n\n", ith);
if (progress)
printf("\nData set # %ld:\n", ith);
}
for (jumb = 1; jumb <= njumble; jumb++)
maketree();
if (usertree)
for (i = 0; i < MAXSHIMOTREES; i++)
free(l0gf[i]);
}
FClose(outfile);
FClose(outtree);
#ifdef MAC
fixmacfile(outfilename);
fixmacfile(outtreename);
#endif
printf("\nDone.\n\n");
#ifdef WIN32
phyRestoreConsoleAttributes();
#endif
ajPhyloFreqDel(&phylofreq);
ajPhyloTreeDelarray(&phylotrees);
ajFileClose(&embossoutfile);
ajFileClose(&embossouttree);
embExit();
return 0;
}
PHYLIPNEW-3.69.650/src/consense.c 0000664 0001750 0001750 00000016240 11305225544 013042 0000000 0000000 #include "phylip.h"
#include "cons.h"
/* version 3.6. (c) Copyright 1993-2008 by the University of Washington.
Written by Joseph Felsenstein, Hisashi Horino,
Akiko Fuseki, Dan Fineman, Sean Lamont, and Andrew Keeffe.
Permission is granted
to copy and use this program provided no fee is charged for it and
provided that this copyright notice is not removed. */
/* The following extern's refer to things declared in cons.c */
AjPPhyloTree* phylotrees = NULL;
extern int tree_pairing;
extern Char intreename[FNMLNGTH], intree2name[FNMLNGTH];
const char* outfilename;
const char* outtreename;
AjPFile embossoutfile;
AjPFile embossouttree;
long trees_in;
extern node *root;
extern long numopts, outgrno, col, setsz;
extern long maxgrp; /* max. no. of groups in all trees found */
extern boolean trout, firsttree, noroot, outgropt, didreroot, prntsets,
progress, treeprint, goteof, strict, mr, mre, ml;
extern pointarray nodep; /* pointers to all nodes in tree */
extern group_type **grouping, **grping2, **group2;/* to store groups found */
extern long **order, **order2, lasti;
extern group_type *fullset;
extern long tipy;
extern double trweight, ntrees, mlfrac;
#ifndef OLDC
/* function prototypes */
//void getoptions(void);
void emboss_getoptions(char *pgm, int argc, char *argv[]);
void count_siblings(node **p);
void treeout(node *);
/* function prototypes */
#endif
void emboss_getoptions(char *pgm, int argc, char *argv[])
{
AjPStr method;
/* Initial settings */
ibmpc = IBMCRT;
ansi = ANSICRT;
didreroot = false;
firsttree = true;
spp = 0 ;
col = 0 ;
/* This is needed so functions in cons.c work */
tree_pairing = NO_PAIRING ;
strict = false;
mr = false;
mre = false;
ml = false;
mlfrac = 0.5;
noroot = true;
numopts = 0;
outgrno = 1;
outgropt = false;
trout = true;
prntsets = true;
progress = true;
treeprint = true;
embInitPV(pgm, argc, argv,"PHYLIPNEW",VERSION);
phylotrees = ajAcdGetTree("intreefile");
trees_in = 0;
while (phylotrees[trees_in])
trees_in++;
method = ajAcdGetListSingle("method");
if (ajStrMatchC(method, "strict")) strict = true;
else if(ajStrMatchC(method, "mr")) mr = true;
else if(ajStrMatchC(method, "mre")) mre = true;
else if(ajStrMatchC(method, "ml")) {
ml = true;
mlfrac = ajAcdGetFloat("mlfrac");
}
prntsets = ajAcdGetBoolean("prntsets");
progress = ajAcdGetBoolean("progress");
treeprint = ajAcdGetBoolean("treeprint");
trout = ajAcdGetToggle("trout");
outgrno = ajAcdGetInt("outgrno");
if(outgrno != 0) outgropt = true;
else outgrno = 1;
noroot = !ajAcdGetToggle("root");
embossoutfile = ajAcdGetOutfile("outfile");
emboss_openfile(embossoutfile, &outfile, &outfilename);
if(trout) {
embossouttree = ajAcdGetOutfile("outtreefile");
emboss_openfile(embossouttree, &outtree, &outtreename);
}
fprintf(outfile, "\nConsensus tree");
fprintf(outfile, " program, version %s\n\n", VERSION);
ajStrDel(&method);
return;
} /* emboss_getoptions */
void count_siblings(node **p)
{
node *tmp_node;
int i;
if (!(*p)) {
/* This is a leaf, */
return;
} else {
tmp_node = (*p)->next;
}
for (i = 0 ; i < 1000; i++) {
if (tmp_node == (*p)) {
/* When we've gone through all the siblings, */
break;
} else if (tmp_node) {
tmp_node = tmp_node->next;
} else {
/* Should this be executed? */
return ;
}
}
} /* count_siblings */
void treeout(node *p)
{
/* write out file with representation of final tree */
long i, n = 0;
Char c;
node *q;
double x;
count_siblings (&p);
if (p->tip) {
/* If we're at a node which is a leaf, figure out how long the
name is and print it out. */
for (i = 1; i <= MAXNCH; i++) {
if (p->nayme[i - 1] != '\0')
n = i;
}
for (i = 0; i < n; i++) {
c = p->nayme[i];
if (c == ' ')
c = '_';
putc(c, outtree);
}
col += n;
} else {
/* If we're at a furcation, print out the proper formatting, loop
through all the children, calling the procedure recursively. */
putc('(', outtree);
col++;
q = p->next;
while (q != p) {
/* This should terminate when we've gone through all the
siblings, */
treeout(q->back);
q = q->next;
if (q == p)
break;
putc(',', outtree);
col++;
if (col > 60) {
putc('\n', outtree);
col = 0;
}
}
putc(')', outtree);
col++;
}
if (p->tip)
x = ntrees;
else
x = (double)p->deltav;
if (p == root) {
/* When we're all done with this tree, */
fprintf(outtree, ";\n");
return;
}
/* Figure out how many characters the branch length requires: */
else {
if (!strict) {
if (x >= 100.0) {
fprintf(outtree, ":%5.1f", x);
col += 4;
} else if (x >= 10.0) {
fprintf(outtree, ":%4.1f", x);
col += 3;
} else if (x >= 1.00) {
fprintf(outtree, ":%4.2f", x);
col += 3;
}
}
}
} /* treeout */
int main(int argc, Char *argv[])
{
/* Local variables added by Dan F. */
pattern_elm ***pattern_array;
long i, j;
long tip_count = 0;
node *p, *q;
#ifdef MAC
argc = 1; /* macsetup("Consense", ""); */
argv[0] = "Consense";
#endif
init(argc, argv);
emboss_getoptions("fconsense", argc, argv);
ntrees = 0.0;
maxgrp = 32767; /* initial size of set hash table */
lasti = -1;
if (prntsets)
fprintf(outfile, "Species in order: \n\n");
countcomma(ajStrGetuniquePtr(&phylotrees[0]->Tree),&tip_count);
tip_count++; /* countcomma does a raw comma count, tips is one greater */
/* Read the tree file and put together grouping, order, and timesseen */
read_groups (&pattern_array, trees_in, tip_count, phylotrees);
/* Compute the consensus tree. */
putc('\n', outfile);
nodep = (pointarray)Malloc(2*(1+spp)*sizeof(node *));
for (i = 0; i < spp; i++) {
nodep[i] = (node *)Malloc(sizeof(node));
for (j = 0; j < MAXNCH; j++)
nodep[i]->nayme[j] = '\0';
strncpy(nodep[i]->nayme, nayme[i], MAXNCH);
}
for (i = spp; i < 2*(1+spp); i++)
nodep[i] = NULL;
consensus(pattern_array, trees_in);
printf("\n");
if (trout) {
treeout(root);
if (progress)
printf("Consensus tree written to file \"%s\"\n\n", outtreename);
}
if (progress)
printf("Output written to file \"%s\"\n\n", outfilename);
for (i = 0; i < spp; i++)
free(nodep[i]);
for (i = spp; i < 2*(1 + spp); i++) {
if (nodep[i] != NULL) {
p = nodep[i]->next;
do {
q = p->next;
free(p);
p = q;
} while (p != nodep[i]);
free(p);
}
}
free(nodep);
FClose(outtree);
FClose(intree);
FClose(outfile);
#ifdef MAC
fixmacfile(outfilename);
fixmacfile(outtreename);
#endif
printf("Done.\n\n");
#ifdef WIN32
phyRestoreConsoleAttributes();
#endif
ajPhyloTreeDelarray(&phylotrees);
ajFileClose(&embossoutfile);
ajFileClose(&embossouttree);
clean_up_final_consense();
embExit();
return 0;
} /* main */
PHYLIPNEW-3.69.650/src/kitsch.c 0000664 0001750 0001750 00000057571 11325562224 012527 0000000 0000000 /* version 3.6. (c) Copyright 1993-2004 by the University of Washington.
Written by Joseph Felsenstein, Akiko Fuseki, Sean Lamont, and Andrew Keeffe.
Permission is granted to copy and use this program provided no fee is
charged for it and provided that this copyright notice is not removed. */
#include
#include "phylip.h"
#include "dist.h"
#define epsilonk 0.000001 /* a very small but not too small number */
AjPPhyloDist* phylodists = NULL;
AjPPhyloTree* phylotrees;
#ifndef OLDC
/* function prototypes */
//void getoptions(void);
void emboss_getoptions(char *pgm, int argc, char *argv[]);
void doinit(void);
void inputoptions(void);
void getinput(void);
void input_data(void);
void add(node *, node *, node *);
void re_move(node **, node **);
void scrunchtraverse(node *, node **, double *);
void combine(node *, node *);
void scrunch(node *);
void secondtraverse(node *, node *, node *, node *, long, long,
long , double *);
void firstraverse(node *, node *, double *);
void sumtraverse(node *, double *);
void evaluate(node *);
void tryadd(node *, node **, node **);
void addpreorder(node *, node *, node *);
void tryrearr(node *, node **, boolean *);
void repreorder(node *, node **, boolean *);
void rearrange(node **);
void dtraverse(node *);
void describe(void);
void copynode(node *, node *);
void copy_(tree *, tree *);
void maketree(void);
/* function prototypes */
#endif
const char* outfilename;
const char* outtreename;
AjPFile embossoutfile;
AjPFile embossouttree;
Char infilename[FNMLNGTH], intreename[FNMLNGTH];
long nonodes, numtrees, col, datasets, ith, njumble, jumb;
/* numtrees is used by usertree option part of maketree */
long inseed;
tree curtree, bestree; /* pointers to all nodes in tree */
boolean minev, jumble, usertree, lower, upper, negallowed, replicates, trout,
printdata, progress, treeprint, mulsets, firstset;
longer seed;
double power;
long *enterorder;
/* Local variables for maketree, propagated globally for C version: */
long examined;
double like, bestyet;
node *there;
boolean *names;
Char ch;
char *progname;
double trweight; /* to make treeread happy */
boolean goteof, haslengths, lengths; /* ditto ... */
void emboss_getoptions(char *pgm, int argc, char *argv[])
{
AjPStr matrixtype = NULL;
long inseed0;
minev = false;
jumble = false;
njumble = 1;
lower = false;
negallowed = false;
power = 2.0;
replicates = false;
upper = false;
usertree = false;
trout = true;
printdata = false;
progress = true;
treeprint = true;
mulsets = false;
datasets = 1;
embInitPV(pgm, argc, argv, "PHYLIPNEW",VERSION);
matrixtype = ajAcdGetListSingle("matrixtype");
if(ajStrMatchC(matrixtype, "l")) lower = true;
else if(ajStrMatchC(matrixtype, "u")) upper = true;
phylodists = ajAcdGetDistances("datafile");
while (phylodists[datasets])
datasets++;
minev = ajAcdGetBoolean("minev");
phylotrees = ajAcdGetTree("intreefile");
if (phylotrees)
{
numtrees = 0;
while (phylotrees[numtrees])
numtrees++;
usertree = true;
}
power = ajAcdGetFloat("power");
if(minev) negallowed = true;
else negallowed = ajAcdGetBoolean("negallowed");
replicates = ajAcdGetBoolean("replicates");
if(!usertree) {
njumble = ajAcdGetInt("njumble");
if(njumble >0) {
inseed = ajAcdGetInt("seed");
jumble = true;
emboss_initseed(inseed, &inseed0, seed);
}
else njumble = 1;
}
//if mulsets and not jumble do jumble
printdata = ajAcdGetBoolean("printdata");
progress = ajAcdGetBoolean("progress");
treeprint = ajAcdGetBoolean("treeprint");
trout = ajAcdGetToggle("trout");
embossoutfile = ajAcdGetOutfile("outfile");
embossouttree = ajAcdGetOutfile("outtreefile");
emboss_openfile(embossoutfile, &outfile, &outfilename);
if(trout) emboss_openfile(embossouttree, &outtree, &outtreename);
/*
printf("\n inseed: %ld",(inseed));
printf("\n jumble: %s",(jumble ? "true" : "false"));
printf("\n njumble: %ld",(njumble));
printf("\n lengths: %s",(lengths ? "true" : "false"));
printf("\n lower: %s",(lower ? "true" : "false"));
printf("\n negallowed: %s",(negallowed ? "true" : "false"));
printf("\n power: %f",(power));
printf("\n replicates: %s",(replicates ? "true" : "false"));
printf("\n trout: %s",(trout ? "true" : "false"));
printf("\n upper: %s",(upper ? "true" : "false"));
printf("\n usertree: %s",(usertree ? "true" : "false"));
printf("\n printdata: %s",(printdata ? "true" : "false"));
printf("\n progress: %s",(progress ? "true" : "false"));
printf("\n treeprint: %s",(treeprint ? "true" : "false"));
printf("\n mulsets: %s",(mulsets ? "true" : "false"));
printf("\n datasets: %s",(datasets ? "true" : "false"));
*/
} /* emboss_getoptions */
void doinit()
{
/* initializes variables */
inputnumbers2seq(phylodists[0], &spp, &nonodes, 1);
alloctree(&curtree.nodep, nonodes);
allocd(nonodes, curtree.nodep);
allocw(nonodes, curtree.nodep);
if (!usertree && njumble > 1) {
alloctree(&bestree.nodep, nonodes);
allocd(nonodes, bestree.nodep);
allocw(nonodes, bestree.nodep);
}
nayme = (naym *)Malloc(spp*sizeof(naym));
enterorder = (long *)Malloc(spp*sizeof(long));
} /* doinit */
void inputoptions()
{
/* print options information */
if (!firstset)
samenumspseq2(phylodists[ith-1], ith);
fprintf(outfile, "\nFitch-Margoliash method ");
fprintf(outfile, "with contemporary tips, version %s\n\n",VERSION);
if (minev)
fprintf(outfile, "Minimum evolution method option\n\n");
fprintf(outfile, " __ __ 2\n");
fprintf(outfile, " \\ \\ (Obs - Exp)\n");
fprintf(outfile, "Sum of squares = /_ /_ ------------\n");
fprintf(outfile, " ");
if (power == (long)power)
fprintf(outfile, "%2ld\n", (long)power);
else
fprintf(outfile, "%4.1f\n", power);
fprintf(outfile, " i j Obs\n\n");
fprintf(outfile, "negative branch lengths");
if (!negallowed)
fprintf(outfile, " not");
fprintf(outfile, " allowed\n\n");
} /* inputoptions */
void getinput()
{
/* reads the input data */
inputoptions();
} /* getinput */
void input_data()
{
/* read in distance matrix */
long i, j, k, columns;
ajint ipos=0;
columns = replicates ? 4 : 6;
if (printdata) {
fprintf(outfile, "\nName Distances");
if (replicates)
fprintf(outfile, " (replicates)");
fprintf(outfile, "\n---- ---------");
if (replicates)
fprintf(outfile, "-------------");
fprintf(outfile, "\n\n");
}
setuptree(&curtree, nonodes);
if (!usertree && njumble > 1)
setuptree(&bestree, nonodes);
for (i = 0; i < (spp); i++) {
curtree.nodep[i]->d[i] = 0.0;
curtree.nodep[i]->w[i] = 0.0;
curtree.nodep[i]->weight = 0.0;
initnamedist(phylodists[ith-1], i);
for (j = 1; j <= (spp); j++) {
curtree.nodep[i]->d[j - 1] = phylodists[ith-1]->Data[ipos];
curtree.nodep[i]->w[j - 1] = phylodists[ith-1]->Replicates[ipos++];
}
}
if (printdata) {
for (i = 0; i < (spp); i++) {
for (j = 0; j < nmlngth; j++)
putc(nayme[i][j], outfile);
putc(' ', outfile);
for (j = 1; j <= (spp); j++) {
fprintf(outfile, "%10.5f", curtree.nodep[i]->d[j - 1]);
if (replicates)
fprintf(outfile, " (%3ld)", (long)curtree.nodep[i]->w[j - 1]);
if (j % columns == 0 && j < spp) {
putc('\n', outfile);
for (k = 1; k <= nmlngth + 1; k++)
putc(' ', outfile);
}
}
putc('\n', outfile);
}
putc('\n', outfile);
}
for (i = 0; i < (spp); i++) {
for (j = 0; j < (spp); j++) {
if (i + 1 != j + 1) {
if (curtree.nodep[i]->d[j] < epsilonk)
curtree.nodep[i]->d[j] = epsilonk;
curtree.nodep[i]->w[j] /= exp(power * log(curtree.nodep[i]->d[j]));
}
}
}
} /* inputdata */
void add(node *below, node *newtip, node *newfork)
{
/* inserts the nodes newfork and its left descendant, newtip,
to the tree. below becomes newfork's right descendant */
if (below != curtree.nodep[below->index - 1])
below = curtree.nodep[below->index - 1];
if (below->back != NULL)
below->back->back = newfork;
newfork->back = below->back;
below->back = newfork->next->next;
newfork->next->next->back = below;
newfork->next->back = newtip;
newtip->back = newfork->next;
if (curtree.root == below)
curtree.root = newfork;
curtree.root->back = NULL;
} /* add */
void re_move(node **item, node **fork)
{
/* removes nodes item and its ancestor, fork, from the tree.
the new descendant of fork's ancestor is made to be
fork's second descendant (other than item). Also
returns pointers to the deleted nodes, item and fork */
node *p, *q;
if ((*item)->back == NULL) {
*fork = NULL;
return;
}
*fork = curtree.nodep[(*item)->back->index - 1];
if (curtree.root == *fork) {
if (*item == (*fork)->next->back)
curtree.root = (*fork)->next->next->back;
else
curtree.root = (*fork)->next->back;
}
p = (*item)->back->next->back;
q = (*item)->back->next->next->back;
if (p != NULL)
p->back = q;
if (q != NULL)
q->back = p;
(*fork)->back = NULL;
p = (*fork)->next;
while (p != *fork) {
p->back = NULL;
p = p->next;
}
(*item)->back = NULL;
} /* remove */
void scrunchtraverse(node *u, node **closest, double *tmax)
{
/* traverse to find closest node to the current one */
if (!u->sametime) {
if (u->t > *tmax) {
*closest = u;
*tmax = u->t;
}
return;
}
u->t = curtree.nodep[u->back->index - 1]->t;
if (!u->tip) {
scrunchtraverse(u->next->back, closest,tmax);
scrunchtraverse(u->next->next->back, closest,tmax);
}
} /* scrunchtraverse */
void combine(node *a, node *b)
{
/* put node b into the set having the same time as a */
if (a->weight + b->weight <= 0.0)
a->t = 0.0;
else
a->t = (a->t * a->weight + b->t * b->weight) / (a->weight + b->weight);
a->weight += b->weight;
b->sametime = true;
} /* combine */
void scrunch(node *s)
{
/* see if nodes can be combined to prevent negative lengths */
double tmax;
node *closest;
boolean found;
closest = NULL;
tmax = -1.0;
do {
if (!s->tip) {
scrunchtraverse(s->next->back, &closest,&tmax);
scrunchtraverse(s->next->next->back, &closest,&tmax);
}
found = (tmax > s->t);
if (found)
combine(s, closest);
tmax = -1.0;
} while (found);
} /* scrunch */
void secondtraverse(node *a, node *q, node *u, node *v, long i, long j,
long k, double *sum)
{
/* recalculate distances, add to sum */
long l;
double wil, wjl, wkl, wli, wlj, wlk, TEMP;
if (!(a->processed || a->tip)) {
secondtraverse(a->next->back, q,u,v,i,j,k,sum);
secondtraverse(a->next->next->back, q,u,v,i,j,k,sum);
return;
}
if (!(a != q && a->processed))
return;
l = a->index;
wil = u->w[l - 1];
wjl = v->w[l - 1];
wkl = wil + wjl;
wli = a->w[i - 1];
wlj = a->w[j - 1];
wlk = wli + wlj;
q->w[l - 1] = wkl;
a->w[k - 1] = wlk;
if (wkl <= 0.0)
q->d[l - 1] = 0.0;
else
q->d[l - 1] = (wil * u->d[l - 1] + wjl * v->d[l - 1]) / wkl;
if (wlk <= 0.0)
a->d[k - 1] = 0.0;
else
a->d[k - 1] = (wli * a->d[i - 1] + wlj * a->d[j - 1]) / wlk;
if (minev)
return;
if (wkl > 0.0) {
TEMP = u->d[l - 1] - v->d[l - 1];
(*sum) += wil * wjl / wkl * (TEMP * TEMP);
}
if (wlk > 0.0) {
TEMP = a->d[i - 1] - a->d[j - 1];
(*sum) += wli * wlj / wlk * (TEMP * TEMP);
}
} /* secondtraverse */
void firstraverse(node *q_, node *r, double *sum)
{ /* firsttraverse */
/* go through tree calculating branch lengths */
node *q;
long i, j, k;
node *u, *v;
q = q_;
if (q == NULL)
return;
q->sametime = false;
if (!q->tip) {
firstraverse(q->next->back, r,sum);
firstraverse(q->next->next->back, r,sum);
}
q->processed = true;
if (q->tip)
return;
u = q->next->back;
v = q->next->next->back;
i = u->index;
j = v->index;
k = q->index;
if (u->w[j - 1] + v->w[i - 1] <= 0.0)
q->t = 0.0;
else
q->t = (u->w[j - 1] * u->d[j - 1] + v->w[i - 1] * v->d[i - 1]) /
(2.0 * (u->w[j - 1] + v->w[i - 1]));
q->weight = u->weight + v->weight + u->w[j - 1] + v->w[i - 1];
if (!negallowed)
scrunch(q);
u->v = q->t - u->t;
v->v = q->t - v->t;
u->back->v = u->v;
v->back->v = v->v;
secondtraverse(r,q,u,v,i,j,k,sum);
} /* firstraverse */
void sumtraverse(node *q, double *sum)
{
/* traverse to finish computation of sum of squares */
long i, j;
node *u, *v;
double TEMP, TEMP1;
if (minev && (q != curtree.root))
*sum += q->v;
if (q->tip)
return;
sumtraverse(q->next->back, sum);
sumtraverse(q->next->next->back, sum);
if (!minev) {
u = q->next->back;
v = q->next->next->back;
i = u->index;
j = v->index;
TEMP = u->d[j - 1] - 2.0 * q->t;
TEMP1 = v->d[i - 1] - 2.0 * q->t;
(*sum) += u->w[j - 1] * (TEMP * TEMP) + v->w[i - 1] * (TEMP1 * TEMP1);
}
} /* sumtraverse */
void evaluate(node *r)
{
/* fill in times and evaluate sum of squares for tree */
double sum;
long i;
sum = 0.0;
for (i = 0; i < (nonodes); i++)
curtree.nodep[i]->processed = curtree.nodep[i]->tip;
firstraverse(r, r,&sum);
sumtraverse(r, &sum);
examined++;
if (replicates && (lower || upper))
sum /= 2;
like = -sum;
} /* evaluate */
void tryadd(node *p, node **item, node **nufork)
{
/* temporarily adds one fork and one tip to the tree.
if the location where they are added yields greater
"likelihood" than other locations tested up to that
time, then keeps that location as there */
add(p, *item, *nufork);
evaluate(curtree.root);
if (like > bestyet) {
bestyet = like;
there = p;
}
re_move(item, nufork);
} /* tryadd */
void addpreorder(node *p, node *item, node *nufork)
{
/* traverses a binary tree, calling PROCEDURE tryadd
at a node before calling tryadd at its descendants */
if (p == NULL)
return;
tryadd(p, &item,&nufork);
if (!p->tip) {
addpreorder(p->next->back, item, nufork);
addpreorder(p->next->next->back, item, nufork);
}
} /* addpreorder */
void tryrearr(node *p, node **r, boolean *success)
{
/* evaluates one rearrangement of the tree.
if the new tree has greater "likelihood" than the old
one sets success := TRUE and keeps the new tree.
otherwise, restores the old tree */
node *frombelow, *whereto, *forknode;
double oldlike;
if (p->back == NULL)
return;
forknode = curtree.nodep[p->back->index - 1];
if (forknode->back == NULL)
return;
oldlike = like;
if (p->back->next->next == forknode)
frombelow = forknode->next->next->back;
else
frombelow = forknode->next->back;
whereto = forknode->back;
re_move(&p, &forknode);
add(whereto, p, forknode);
if ((*r)->back != NULL)
*r = curtree.nodep[(*r)->back->index - 1];
evaluate(*r);
if (like - oldlike > LIKE_EPSILON) {
bestyet = like;
*success = true;
return;
}
re_move(&p, &forknode);
add(frombelow, p, forknode);
if ((*r)->back != NULL)
*r = curtree.nodep[(*r)->back->index - 1];
like = oldlike;
} /* tryrearr */
void repreorder(node *p, node **r, boolean *success)
{
/* traverses a binary tree, calling PROCEDURE tryrearr
at a node before calling tryrearr at its descendants */
if (p == NULL)
return;
tryrearr(p,r,success);
if (!p->tip) {
repreorder(p->next->back,r,success);
repreorder(p->next->next->back,r,success);
}
} /* repreorder */
void rearrange(node **r_)
{
/* traverses the tree (preorder), finding any local
rearrangement which decreases the number of steps.
if traversal succeeds in increasing the tree's
"likelihood", PROCEDURE rearrange runs traversal again */
node **r;
boolean success;
r = r_;
success = true;
while (success) {
success = false;
repreorder(*r,r,&success);
}
} /* rearrange */
void dtraverse(node *q)
{
/* print table of lengths etc. */
long i;
if (!q->tip)
dtraverse(q->next->back);
if (q->back != NULL) {
fprintf(outfile, "%4ld ", q->back->index - spp);
if (q->index <= spp) {
for (i = 0; i < nmlngth; i++)
putc(nayme[q->index - 1][i], outfile);
} else
fprintf(outfile, "%4ld ", q->index - spp);
fprintf(outfile, "%13.5f", curtree.nodep[q->back->index - 1]->t - q->t);
q->v = curtree.nodep[q->back->index - 1]->t - q->t;
q->back->v = q->v;
fprintf(outfile, "%16.5f\n", curtree.root->t - q->t);
}
if (!q->tip)
dtraverse(q->next->next->back);
} /* dtraverse */
void describe()
{
/* prints table of lengths, times, sum of squares, etc. */
long i, j;
double totalnum;
double TEMP;
if (!minev)
fprintf(outfile, "\nSum of squares = %10.3f\n\n", -like);
else
fprintf(outfile, "Sum of branch lengths = %10.3f\n\n", -like);
if ((fabs(power - 2) < 0.01) && !minev) {
totalnum = 0.0;
for (i = 0; i < (spp); i++) {
for (j = 0; j < (spp); j++) {
if (i + 1 != j + 1 && curtree.nodep[i]->d[j] > 0.0) {
TEMP = curtree.nodep[i]->d[j];
totalnum += curtree.nodep[i]->w[j] * (TEMP * TEMP);
}
}
}
totalnum -= 2;
if (replicates && (lower || upper))
totalnum /= 2;
fprintf(outfile, "Average percent standard deviation =");
fprintf(outfile, "%10.5f\n\n", 100 * sqrt(-(like / totalnum)));
}
fprintf(outfile, "From To Length Height\n");
fprintf(outfile, "---- -- ------ ------\n\n");
dtraverse(curtree.root);
putc('\n', outfile);
if (trout) {
col = 0;
treeoutr(curtree.root,&col,&curtree);
}
} /* describe */
void copynode(node *c, node *d)
{
/* make a copy of a node */
memcpy(d->d, c->d, nonodes*sizeof(double));
memcpy(d->w, c->w, nonodes*sizeof(double));
d->t = c->t;
d->sametime = c->sametime;
d->weight = c->weight;
d->processed = c->processed;
d->xcoord = c->xcoord;
d->ycoord = c->ycoord;
d->ymin = c->ymin;
d->ymax = c->ymax;
} /* copynode */
void copy_(tree *a, tree *b)
{
/* make a copy of a tree */
long i, j=0;
node *p, *q;
for (i = 0; i < spp; i++) {
copynode(a->nodep[i], b->nodep[i]);
if (a->nodep[i]->back) {
if (a->nodep[i]->back == a->nodep[a->nodep[i]->back->index - 1])
b->nodep[i]->back = b->nodep[a->nodep[i]->back->index - 1];
else if (a->nodep[i]->back
== a->nodep[a->nodep[i]->back->index - 1]->next)
b->nodep[i]->back = b->nodep[a->nodep[i]->back->index - 1]->next;
else
b->nodep[i]->back
= b->nodep[a->nodep[i]->back->index - 1]->next->next;
}
else b->nodep[i]->back = NULL;
}
for (i = spp; i < nonodes; i++) {
p = a->nodep[i];
q = b->nodep[i];
for (j = 1; j <= 3; j++) {
copynode(p, q);
if (p->back) {
if (p->back == a->nodep[p->back->index - 1])
q->back = b->nodep[p->back->index - 1];
else if (p->back == a->nodep[p->back->index - 1]->next)
q->back = b->nodep[p->back->index - 1]->next;
else
q->back = b->nodep[p->back->index - 1]->next->next;
}
else
q->back = NULL;
p = p->next;
q = q->next;
}
}
b->root = a->root;
} /* copy */
void maketree()
{
/* constructs a binary tree from the pointers in curtree.nodep.
adds each node at location which yields highest "likelihood"
then rearranges the tree for greatest "likelihood" */
long i, j, which;
double bestlike, bstlike2=0, gotlike;
boolean lastrearr;
node *item, *nufork;
char *treestr;
if (!usertree) {
if (jumb == 1) {
input_data();
examined = 0;
}
for (i = 1; i <= (spp); i++)
enterorder[i - 1] = i;
if (jumble)
randumize(seed, enterorder);
curtree.root = curtree.nodep[enterorder[0] - 1];
add(curtree.nodep[enterorder[0] - 1], curtree.nodep[enterorder[1] - 1],
curtree.nodep[spp]);
if (progress) {
printf("Adding species:\n");
writename(0, 2, enterorder);
#ifdef WIN32
phyFillScreenColor();
#endif
}
for (i = 3; i <= (spp); i++) {
bestyet = -DBL_MAX;
item = curtree.nodep[enterorder[i - 1] - 1];
nufork = curtree.nodep[spp + i - 2];
addpreorder(curtree.root, item, nufork);
add(there, item, nufork);
like = bestyet;
rearrange(&curtree.root);
evaluate(curtree.root);
examined--;
if (progress) {
writename(i - 1, 1, enterorder);
#ifdef WIN32
phyFillScreenColor();
#endif
}
lastrearr = (i == spp);
if (lastrearr) {
if (progress) {
printf("\nDoing global rearrangements\n");
printf(" !");
for (j = 1; j <= (nonodes); j++)
if ( j % (( nonodes / 72 ) + 1 ) == 0 )
putchar('-');
printf("!\n");
#ifdef WIN32
phyFillScreenColor();
#endif
}
bestlike = bestyet;
do {
gotlike = bestlike;
if (progress)
printf(" ");
for (j = 0; j < (nonodes); j++) {
there = curtree.root;
bestyet = -DBL_MAX;
item = curtree.nodep[j];
if (item != curtree.root) {
re_move(&item, &nufork);
there = curtree.root;
addpreorder(curtree.root, item, nufork);
add(there, item, nufork);
}
if (progress) {
if ( j % (( nonodes / 72 ) + 1 ) == 0 )
putchar('.');
fflush(stdout);
}
}
if (progress) {
putchar('\n');
#ifdef WIN32
phyFillScreenColor();
#endif
}
} while (bestlike > gotlike);
if (njumble > 1) {
if (jumb == 1 || (jumb > 1 && bestlike > bstlike2)) {
copy_(&curtree, &bestree);
bstlike2 = bestlike;
}
}
}
}
if (njumble == jumb) {
if (njumble > 1)
copy_(&bestree, &curtree);
evaluate(curtree.root);
printree(curtree.root, treeprint, false, true);
describe();
}
} else {
input_data();
if (treeprint)
fprintf(outfile, "\n\nUser-defined trees:\n\n");
names = (boolean *)Malloc(spp*sizeof(boolean));
which = 1;
while (which <= numtrees ) {
treestr = ajStrGetuniquePtr(&phylotrees[which-1]->Tree);
treeread2 (&treestr, &curtree.root, curtree.nodep,
lengths, &trweight, &goteof, &haslengths, &spp,false,nonodes);
evaluate(curtree.root);
printree(curtree.root, treeprint, false, true);
describe();
which++;
}
FClose(intree);
free(names);
}
if (jumb == njumble && progress) {
printf("\nOutput written to file \"%s\"\n", outfilename);
if (trout)
printf("\nTree also written onto file \"%s\"\n", outtreename);
}
} /* maketree */
int main(int argc, Char *argv[])
{ /* Fitch-Margoliash criterion with contemporary tips */
#ifdef MAC
argc = 1; /* macsetup("Kitsch",""); */
argv[0] = "Kitsch";
#endif
init(argc,argv);
emboss_getoptions("fkitsch",argc,argv);
/* reads in spp, options, and the data, then calls maketree to
construct the tree */
progname = argv[0];
ibmpc = IBMCRT;
ansi = ANSICRT;
firstset = true;
doinit();
for (ith = 1; ith <= datasets; ith++) {
if (datasets > 1) {
fprintf(outfile, "\nData set # %ld:\n",ith);
if (progress)
printf("\nData set # %ld:\n",ith);
}
getinput();
for (jumb = 1; jumb <= njumble; jumb++)
maketree();
firstset = false;
}
FClose(infile);
FClose(outfile);
FClose(outtree);
#ifdef MAC
fixmacfile(outfilename);
fixmacfile(outtreename);
#endif
#ifdef WIN32
phyRestoreConsoleAttributes();
#endif
printf("\nDone.\n\n");
embExit();
return 0;
} /* Fitch-Margoliash criterion with contemporary tips */
PHYLIPNEW-3.69.650/src/fitch.c 0000664 0001750 0001750 00000066105 11325562224 012330 0000000 0000000
#include "phylip.h"
#include "dist.h"
#include "float.h"
/* version 3.6. (c) Copyright 1993-2004 by the University of Washington.
Written by Joseph Felsenstein, Akiko Fuseki, Sean Lamont, and Andrew Keeffe.
Permission is granted to copy and use this program provided no fee is
charged for it and provided that this copyright notice is not removed. */
#define zsmoothings 10 /* number of zero-branch correction iterations */
#define epsilonf 0.000001 /* a very small but not too small number */
#define delta 0.01 /* a not quite so small number */
#define MAXNUMTREES 100000000 /* a number bigger than conceivable numtrees */
AjPPhyloDist* phylodists = NULL;
AjPPhyloTree* phylotrees;
#ifndef OLDC
/* function prototypes */
//void getoptions(void);
void emboss_getoptions(char *pgm, int argc, char *argv[]);
void allocrest(void);
void doinit(void);
void inputoptions(void);
void fitch_getinput(void);
void secondtraverse(node *, double , long *, double *);
void firsttraverse(node *, long *, double *);
double evaluate(tree *);
void nudists(node *, node *);
void makedists(node *);
void makebigv(node *);
void correctv(node *);
void alter(node *, node *);
void nuview(node *);
void update(node *);
void smooth(node *);
void filltraverse(node *, node *, boolean);
void fillin(node *, node *, boolean);
void insert_(node *, node *, boolean);
void copynode(node *, node *);
void copy_(tree *, tree *);
void setuptipf(long, tree *);
void buildnewtip(long , tree *, long);
void buildsimpletree(tree *, long);
void addtraverse(node *, node *, boolean, long *, boolean *);
void re_move(node **, node **);
void rearrange(node *, long *, long *, boolean *);
void describe(node *);
void summarize(long);
void nodeinit(node *);
void initrav(node *);
void treevaluate(void);
void maketree(void);
void globrearrange(long* numtrees,boolean* succeeded);
/* function prototypes */
#endif
const char* outfilename;
const char* outtreename;
AjPFile embossoutfile;
AjPFile embossouttree;
Char infilename[FNMLNGTH], intreename[FNMLNGTH];
long nonodes2, outgrno, nums, col, datasets, ith, njumble, jumb=0, numtrees;
long inseed;
vector *x;
intvector *reps;
boolean minev, global, jumble, lengths, usertree, lower, upper, negallowed,
outgropt, replicates, trout, printdata, progress, treeprint,
mulsets, firstset;
double power;
double trweight; /* to make treeread happy */
boolean goteof, haslengths; /* ditto ... */
boolean first; /* ditto ... */
node *addwhere;
longer seed;
long *enterorder;
tree curtree, priortree, bestree, bestree2;
Char ch;
char *progname;
void emboss_getoptions(char *pgm, int argc, char *argv[])
{
AjPStr matrixtype = NULL;
long inseed0=0;
minev = false;
global = false;
jumble = false;
njumble = 1;
lengths = false;
lower = false;
negallowed = false;
outgrno = 1;
outgropt = false;
power = 2.0;
replicates = false;
trout = true;
upper = false;
usertree = false;
printdata = false;
progress = true;
treeprint = true;
mulsets = false;
datasets = 1;
embInitPV(pgm, argc, argv, "PHYLIPNEW",VERSION);
phylodists = ajAcdGetDistances("datafile");
while (phylodists[datasets])
datasets++;
minev = ajAcdGetBoolean("minev");
phylotrees = ajAcdGetTree("intreefile");
if (phylotrees)
{
numtrees = 0;
while (phylotrees[numtrees])
numtrees++;
usertree = true;
}
power = ajAcdGetFloat("power");
if(minev) negallowed = true;
else negallowed = ajAcdGetBoolean("negallowed");
matrixtype = ajAcdGetListSingle("matrixtype");
if(ajStrMatchC(matrixtype, "l")) lower = true;
else if(ajStrMatchC(matrixtype, "u")) upper = true;
replicates = ajAcdGetBoolean("replicates");
if(!usertree) {
global = ajAcdGetBoolean("global");
njumble = ajAcdGetInt("njumble");
if(njumble >0) {
inseed = ajAcdGetInt("seed");
jumble = true;
emboss_initseed(inseed, &inseed0, seed);
}
else njumble = 1;
}
outgrno = ajAcdGetInt("outgrno");
if(outgrno != 0) outgropt = true;
else outgrno = 1;
printdata = ajAcdGetBoolean("printdata");
progress = ajAcdGetBoolean("progress");
treeprint = ajAcdGetBoolean("treeprint");
trout = ajAcdGetToggle("trout");
embossoutfile = ajAcdGetOutfile("outfile");
embossouttree = ajAcdGetOutfile("outtreefile");
emboss_openfile(embossoutfile, &outfile, &outfilename);
if(trout) emboss_openfile(embossouttree, &outtree, &outtreename);
/*
printf("\n inseed: %ld",(inseed));
printf("\n global: %s",(global ? "true" : "false"));
printf("\n jumble: %s",(jumble ? "true" : "false"));
printf("\n njumble: %ld",(njumble));
printf("\n lengths: %s",(lengths ? "true" : "false"));
printf("\n lower: %s",(lower ? "true" : "false"));
printf("\n negallowed: %s",(negallowed ? "true" : "false"));
printf("\n outgrno: %ld",(outgrno));
printf("\n outgropt: %s",(outgropt ? "true" : "false"));
printf("\n power: %f",(power));
printf("\n replicates: %s",(replicates ? "true" : "false"));
printf("\n trout: %s",(trout ? "true" : "false"));
printf("\n upper: %s",(upper ? "true" : "false"));
printf("\n usertree: %s",(usertree ? "true" : "false"));
printf("\n printdata: %s",(printdata ? "true" : "false"));
printf("\n progress: %s",(progress ? "true" : "false"));
printf("\n treeprint: %s",(treeprint ? "true" : "false"));
printf("\n mulsets: %s",(mulsets ? "true" : "false"));
printf("\n datasets: %ld",(datasets));
*/
} /* emboss_getoptions */
void allocrest()
{
long i;
x = (vector *)Malloc(spp*sizeof(vector));
reps = (intvector *)Malloc(spp*sizeof(intvector));
for (i=0;i 1) {
alloctree(&bestree2.nodep, nonodes2);
allocd(nonodes2, bestree2.nodep);
allocw(nonodes2, bestree2.nodep);
}
}
allocrest();
} /* doinit */
void inputoptions()
{
/* print options information */
if (!firstset)
samenumspseq2(phylodists[ith-1], ith);
fprintf(outfile, "\nFitch-Margoliash method version %s\n\n",VERSION);
if (minev)
fprintf(outfile, "Minimum evolution method option\n\n");
fprintf(outfile, " __ __ 2\n");
fprintf(outfile, " \\ \\ (Obs - Exp)\n");
fprintf(outfile, "Sum of squares = /_ /_ ------------\n");
fprintf(outfile, " ");
if (power == (long)power)
fprintf(outfile, "%2ld\n", (long)power);
else
fprintf(outfile, "%4.1f\n", power);
fprintf(outfile, " i j Obs\n\n");
fprintf(outfile, "Negative branch lengths ");
if (!negallowed)
fprintf(outfile, "not ");
fprintf(outfile, "allowed\n\n");
if (global)
fprintf(outfile, "global optimization\n\n");
} /* inputoptions */
void fitch_getinput()
{
/* reads the input data */
inputoptions();
} /* fitch_getinput */
void secondtraverse(node *q, double y, long *nx, double *sum)
{
/* from each of those places go back to all others */
/* nx comes from firsttraverse */
/* sum comes from evaluate via firsttraverse */
double z=0.0, TEMP=0.0;
z = y + q->v;
if (q->tip) {
TEMP = q->d[(*nx) - 1] - z;
*sum += q->w[(*nx) - 1] * (TEMP * TEMP);
} else {
secondtraverse(q->next->back, z, nx, sum);
secondtraverse(q->next->next->back, z, nx,sum);
}
} /* secondtraverse */
void firsttraverse(node *p, long *nx, double *sum)
{
/* go through tree calculating branch lengths */
if (minev && (p != curtree.start))
*sum += p->v;
if (p->tip) {
if (!minev) {
*nx = p->index;
secondtraverse(p->back, 0.0, nx, sum);
}
} else {
firsttraverse(p->next->back, nx,sum);
firsttraverse(p->next->next->back, nx,sum);
}
} /* firsttraverse */
double evaluate(tree *t)
{
double sum=0.0;
long nx=0;
/* evaluate likelihood of a tree */
firsttraverse(t->start->back ,&nx, &sum);
firsttraverse(t->start, &nx, &sum);
if ((!minev) && replicates && (lower || upper))
sum /= 2;
t->likelihood = -sum;
return (-sum);
} /* evaluate */
void nudists(node *x, node *y)
{
/* compute distance between an interior node and tips */
long nq=0, nr=0, nx=0, ny=0;
double dil=0, djl=0, wil=0, wjl=0, vi=0, vj=0;
node *qprime, *rprime;
qprime = x->next;
rprime = qprime->next->back;
qprime = qprime->back;
ny = y->index;
dil = qprime->d[ny - 1];
djl = rprime->d[ny - 1];
wil = qprime->w[ny - 1];
wjl = rprime->w[ny - 1];
vi = qprime->v;
vj = rprime->v;
x->w[ny - 1] = wil + wjl;
if (wil + wjl <= 0.0)
x->d[ny - 1] = 0.0;
else
x->d[ny - 1] = ((dil - vi) * wil + (djl - vj) * wjl) / (wil + wjl);
nx = x->index;
nq = qprime->index;
nr = rprime->index;
dil = y->d[nq - 1];
djl = y->d[nr - 1];
wil = y->w[nq - 1];
wjl = y->w[nr - 1];
y->w[nx - 1] = wil + wjl;
if (wil + wjl <= 0.0)
y->d[nx - 1] = 0.0;
else
y->d[nx - 1] = ((dil - vi) * wil + (djl - vj) * wjl) / (wil + wjl);
} /* nudists */
void makedists(node *p)
{
/* compute distances among three neighbors of a node */
long i=0, nr=0, ns=0;
node *q, *r, *s;
r = p->back;
nr = r->index;
for (i = 1; i <= 3; i++) {
q = p->next;
s = q->back;
ns = s->index;
if (s->w[nr - 1] + r->w[ns - 1] <= 0.0)
p->dist = 0.0;
else
p->dist = (s->w[nr - 1] * s->d[nr - 1] + r->w[ns - 1] * r->d[ns - 1]) /
(s->w[nr - 1] + r->w[ns - 1]);
p = q;
r = s;
nr = ns;
}
} /* makedists */
void makebigv(node *p)
{
/* make new branch length */
long i=0;
node *temp, *q, *r;
q = p->next;
r = q->next;
for (i = 1; i <= 3; i++) {
if (p->iter) {
p->v = (p->dist + r->dist - q->dist) / 2.0;
p->back->v = p->v;
}
temp = p;
p = q;
q = r;
r = temp;
}
} /* makebigv */
void correctv(node *p)
{
/* iterate branch lengths if some are to be zero */
node *q, *r, *temp;
long i=0, j=0, n=0, nq=0, nr=0, ntemp=0;
double wq=0.0, wr=0.0;
q = p->next;
r = q->next;
n = p->back->index;
nq = q->back->index;
nr = r->back->index;
for (i = 1; i <= zsmoothings; i++) {
for (j = 1; j <= 3; j++) {
if (p->iter) {
wr = r->back->w[n - 1] + p->back->w[nr - 1];
wq = q->back->w[n - 1] + p->back->w[nq - 1];
if (wr + wq <= 0.0 && !negallowed)
p->v = 0.0;
else
p->v = ((p->dist - q->v) * wq + (r->dist - r->v) * wr) / (wr + wq);
if (p->v < 0 && !negallowed)
p->v = 0.0;
p->back->v = p->v;
}
temp = p;
p = q;
q = r;
r = temp;
ntemp = n;
n = nq;
nq = nr;
nr = ntemp;
}
}
} /* correctv */
void alter(node *x, node *y)
{
/* traverse updating these views */
nudists(x, y);
if (!y->tip) {
alter(x, y->next->back);
alter(x, y->next->next->back);
}
} /* alter */
void nuview(node *p)
{
/* renew information about subtrees */
long i=0;
node *q, *r, *pprime, *temp;
q = p->next;
r = q->next;
for (i = 1; i <= 3; i++) {
temp = p;
pprime = p->back;
alter(p, pprime);
p = q;
q = r;
r = temp;
}
} /* nuview */
void update(node *p)
{
/* update branch lengths around a node */
if (p->tip)
return;
makedists(p);
if (p->iter || p->next->iter || p->next->next->iter) {
makebigv(p);
correctv(p);
}
nuview(p);
} /* update */
void smooth(node *p)
{
/* go through tree getting new branch lengths and views */
if (p->tip)
return;
update(p);
smooth(p->next->back);
smooth(p->next->next->back);
} /* smooth */
void filltraverse(node *pb, node *qb, boolean contin)
{
if (qb->tip)
return;
if (contin) {
filltraverse(pb, qb->next->back,contin);
filltraverse(pb, qb->next->next->back,contin);
nudists(qb, pb);
return;
}
if (!qb->next->back->tip)
nudists(qb->next->back, pb);
if (!qb->next->next->back->tip)
nudists(qb->next->next->back, pb);
} /* filltraverse */
void fillin(node *pa, node *qa, boolean contin)
{
if (!pa->tip) {
fillin(pa->next->back, qa, contin);
fillin(pa->next->next->back, qa, contin);
}
filltraverse(pa, qa, contin);
} /* fillin */
void insert_(node *p, node *q, boolean contin_)
{
/* put p and q together and iterate info. on resulting tree */
double x=0.0, oldlike;
hookup(p->next->next, q->back);
hookup(p->next, q);
x = q->v / 2.0;
p->v = 0.0;
p->back->v = 0.0;
p->next->v = x;
p->next->back->v = x;
p->next->next->back->v = x;
p->next->next->v = x;
fillin(p->back, p, contin_);
evaluate(&curtree);
do {
oldlike = curtree.likelihood;
smooth(p);
smooth(p->back);
evaluate(&curtree);
} while (fabs(curtree.likelihood - oldlike) > delta);
} /* insert_ */
void copynode(node *c, node *d)
{
/* make a copy of a node */
memcpy(d->d, c->d, nonodes2*sizeof(double));
memcpy(d->w, c->w, nonodes2*sizeof(double));
d->v = c->v;
d->iter = c->iter;
d->dist = c->dist;
d->xcoord = c->xcoord;
d->ycoord = c->ycoord;
d->ymin = c->ymin;
d->ymax = c->ymax;
} /* copynode */
void copy_(tree *a, tree *b)
{
/* make copy of a tree a to tree b */
long i, j=0;
node *p, *q;
for (i = 0; i < spp; i++) {
copynode(a->nodep[i], b->nodep[i]);
if (a->nodep[i]->back) {
if (a->nodep[i]->back == a->nodep[a->nodep[i]->back->index - 1])
b->nodep[i]->back = b->nodep[a->nodep[i]->back->index - 1];
else if (a->nodep[i]->back
== a->nodep[a->nodep[i]->back->index - 1]->next)
b->nodep[i]->back = b->nodep[a->nodep[i]->back->index - 1]->next;
else
b->nodep[i]->back
= b->nodep[a->nodep[i]->back->index - 1]->next->next;
}
else b->nodep[i]->back = NULL;
}
for (i = spp; i < nonodes2; i++) {
p = a->nodep[i];
q = b->nodep[i];
for (j = 1; j <= 3; j++) {
copynode(p, q);
if (p->back) {
if (p->back == a->nodep[p->back->index - 1])
q->back = b->nodep[p->back->index - 1];
else if (p->back == a->nodep[p->back->index - 1]->next)
q->back = b->nodep[p->back->index - 1]->next;
else
q->back = b->nodep[p->back->index - 1]->next->next;
}
else
q->back = NULL;
p = p->next;
q = q->next;
}
}
b->likelihood = a->likelihood;
b->start = a->start;
} /* copy_ */
void setuptipf(long m, tree *t)
{
/* initialize branch lengths and views in a tip */
long i=0;
intvector n=(long *)Malloc(spp * sizeof(long));
node *WITH;
WITH = t->nodep[m - 1];
memcpy(WITH->d, x[m - 1], (nonodes2 * sizeof(double)));
memcpy(n, reps[m - 1], (spp * sizeof(long)));
for (i = 0; i < spp; i++) {
if (i + 1 != m && n[i] > 0) {
if (WITH->d[i] < epsilonf)
WITH->d[i] = epsilonf;
WITH->w[i] = n[i] / exp(power * log(WITH->d[i]));
} else {
WITH->w[i] = 0.0;
WITH->d[i] = 0.0;
}
}
for (i = spp; i < nonodes2; i++) {
WITH->w[i] = 1.0;
WITH->d[i] = 0.0;
}
WITH->index = m;
if (WITH->iter) WITH->v = 0.0;
free(n);
} /* setuptipf */
void buildnewtip(long m, tree *t, long nextsp)
{
/* initialize and hook up a new tip */
node *p;
setuptipf(m, t);
p = t->nodep[nextsp + spp - 3];
hookup(t->nodep[m - 1], p);
} /* buildnewtip */
void buildsimpletree(tree *t, long nextsp)
{
/* make and initialize a three-species tree */
curtree.start=curtree.nodep[enterorder[0] - 1];
setuptipf(enterorder[0], t);
setuptipf(enterorder[1], t);
hookup(t->nodep[enterorder[0] - 1], t->nodep[enterorder[1] - 1]);
buildnewtip(enterorder[2], t, nextsp);
insert_(t->nodep[enterorder[2] - 1]->back, t->nodep[enterorder[0] - 1],
false);
} /* buildsimpletree */
void addtraverse(node *p, node *q, boolean contin, long *numtrees,
boolean *succeeded)
{
/* traverse through a tree, finding best place to add p */
insert_(p, q, true);
(*numtrees)++;
if (evaluate(&curtree) > (bestree.likelihood +
epsilonf * fabs(bestree.likelihood))){
copy_(&curtree, &bestree);
addwhere = q;
(*succeeded)=true;
}
copy_(&priortree, &curtree);
if (!q->tip && contin) {
addtraverse(p, q->next->back, contin,numtrees,succeeded);
addtraverse(p, q->next->next->back, contin,numtrees,succeeded);
}
} /* addtraverse */
void re_move(node **p, node **q)
{
/* re_move p and record in q where it was */
*q = (*p)->next->back;
hookup(*q, (*p)->next->next->back);
(*p)->next->back = NULL;
(*p)->next->next->back = NULL;
update(*q);
update((*q)->back);
} /* re_move */
void globrearrange(long* numtrees,boolean* succeeded)
{
/* does global rearrangements */
tree globtree;
tree oldtree;
int i,j,k,num_sibs,num_sibs2;
node *where,*sib_ptr,*sib_ptr2;
double oldbestyet = curtree.likelihood;
int success = false;
alloctree(&globtree.nodep,nonodes2);
alloctree(&oldtree.nodep,nonodes2);
setuptree(&globtree,nonodes2);
setuptree(&oldtree,nonodes2);
allocd(nonodes2, globtree.nodep);
allocd(nonodes2, oldtree.nodep);
allocw(nonodes2, globtree.nodep);
allocw(nonodes2, oldtree.nodep);
copy_(&curtree,&globtree);
copy_(&curtree,&oldtree);
for ( i = spp ; i < nonodes2 ; i++ ) {
num_sibs = count_sibs(curtree.nodep[i]);
sib_ptr = curtree.nodep[i];
if ( (i - spp) % (( nonodes2 / 72 ) + 1 ) == 0 )
putchar('.');
fflush(stdout);
for ( j = 0 ; j <= num_sibs ; j++ ) {
re_move(&sib_ptr,&where);
copy_(&curtree,&priortree);
if (where->tip) {
copy_(&oldtree,&curtree);
copy_(&oldtree,&bestree);
sib_ptr=sib_ptr->next;
continue;
}
else num_sibs2 = count_sibs(where);
sib_ptr2 = where;
for ( k = 0 ; k < num_sibs2 ; k++ ) {
addwhere = NULL;
addtraverse(sib_ptr,sib_ptr2->back,true,numtrees,succeeded);
if ( addwhere && where != addwhere && where->back != addwhere
&& bestree.likelihood > globtree.likelihood) {
copy_(&bestree,&globtree);
success = true;
}
sib_ptr2 = sib_ptr2->next;
}
copy_(&oldtree,&curtree);
copy_(&oldtree,&bestree);
sib_ptr = sib_ptr->next;
}
}
copy_(&globtree,&curtree);
copy_(&globtree,&bestree);
if (success && globtree.likelihood > oldbestyet) {
*succeeded = true;
}
else {
*succeeded = false;
}
freed(nonodes2, globtree.nodep);
freed(nonodes2, oldtree.nodep);
freew(nonodes2, globtree.nodep);
freew(nonodes2, oldtree.nodep);
freetree(&globtree.nodep,nonodes2);
freetree(&oldtree.nodep,nonodes2);
}
void rearrange(node *p, long *numtrees, long *nextsp, boolean *succeeded)
{
node *q, *r;
if (!p->tip && !p->back->tip) {
r = p->next->next;
re_move(&r, &q);
copy_(&curtree, &priortree);
addtraverse(r, q->next->back, false, numtrees,succeeded);
addtraverse(r, q->next->next->back, false, numtrees,succeeded);
copy_(&bestree, &curtree);
if (global && ((*nextsp) == spp)) {
putchar('.');
fflush(stdout);
}
}
if (!p->tip) {
rearrange(p->next->back, numtrees,nextsp,succeeded);
rearrange(p->next->next->back, numtrees,nextsp,succeeded);
}
} /* rearrange */
void describe(node *p)
{
/* print out information for one branch */
long i=0;
node *q;
q = p->back;
fprintf(outfile, "%4ld ", q->index - spp);
if (p->tip) {
for (i = 0; i < nmlngth; i++)
putc(nayme[p->index - 1][i], outfile);
} else
fprintf(outfile, "%4ld ", p->index - spp);
fprintf(outfile, "%15.5f\n", q->v);
if (!p->tip) {
describe(p->next->back);
describe(p->next->next->back);
}
} /* describe */
void summarize(long numtrees)
{
/* print out branch lengths etc. */
long i, j, totalnum;
fprintf(outfile, "\nremember:");
if (outgropt)
fprintf(outfile, " (although rooted by outgroup)");
fprintf(outfile, " this is an unrooted tree!\n\n");
if (!minev)
fprintf(outfile, "Sum of squares = %11.5f\n\n", -curtree.likelihood);
else
fprintf(outfile, "Sum of branch lengths = %11.5f\n\n", -curtree.likelihood);
if ((power == 2.0) && !minev) {
totalnum = 0;
for (i = 1; i <= nums; i++) {
for (j = 1; j <= nums; j++) {
if (i != j)
totalnum += reps[i - 1][j - 1];
}
}
fprintf(outfile, "Average percent standard deviation = ");
fprintf(outfile, "%11.5f\n\n",
100 * sqrt(-curtree.likelihood / (totalnum - 2)));
}
fprintf(outfile, "Between And Length\n");
fprintf(outfile, "------- --- ------\n");
describe(curtree.start->next->back);
describe(curtree.start->next->next->back);
describe(curtree.start->back);
fprintf(outfile, "\n\n");
if (trout) {
col = 0;
treeout(curtree.start, &col, 0.43429445222, true,
curtree.start);
}
} /* summarize */
void nodeinit(node *p)
{
/* initialize a node */
long i, j;
for (i = 1; i <= 3; i++) {
for (j = 0; j < nonodes2; j++) {
p->w[j] = 1.0;
p->d[j] = 0.0;
}
p = p->next;
}
if ((!lengths) || p->iter)
p->v = 1.0;
if ((!lengths) || p->back->iter)
p->back->v = 1.0;
} /* nodeinit */
void initrav(node *p)
{
/* traverse to initialize */
if (p->tip)
return;
nodeinit(p);
initrav(p->next->back);
initrav(p->next->next->back);
} /* initrav */
void treevaluate()
{
/* evaluate user-defined tree, iterating branch lengths */
long i;
double oldlike;
for (i = 1; i <= spp; i++)
setuptipf(i, &curtree);
unroot(&curtree,nonodes2);
initrav(curtree.start);
if (curtree.start->back != NULL) {
initrav(curtree.start->back);
evaluate(&curtree);
do {
oldlike = curtree.likelihood;
smooth(curtree.start);
evaluate(&curtree);
} while (fabs(curtree.likelihood - oldlike) > delta);
}
evaluate(&curtree);
} /* treevaluate */
void maketree()
{
/* contruct the tree */
long nextsp;
boolean succeeded=false;
long i, j, which;
char* treestr;
if (usertree) {
dist_inputdata(phylodists[ith-1], replicates, printdata,
lower, upper, x, reps);
setuptree(&curtree, nonodes2);
for (which = 1; which <= spp; which++)
setuptipf(which, &curtree);
if (numtrees > MAXNUMTREES) {
printf("\nERROR: number of input trees is read incorrectly from %s\n",
intreename);
embExitBad();
}
if (treeprint) {
fprintf(outfile, "User-defined tree");
if (numtrees > 1)
putc('s', outfile);
fprintf(outfile, ":\n\n");
}
first = true;
which = 1;
while (which <= numtrees) {
treestr = ajStrGetuniquePtr(&phylotrees[which-1]->Tree);
treeread2 (&treestr, &curtree.start, curtree.nodep,
lengths, &trweight, &goteof, &haslengths, &spp,false,nonodes2);
nums = spp;
curtree.start = curtree.nodep[outgrno - 1]->back;
treevaluate();
printree(curtree.start, treeprint, false, false);
summarize(numtrees);
clear_connections(&curtree,nonodes2);
which++;
}
FClose(intree);
} else {
if (jumb == 1) {
dist_inputdata(phylodists[ith-1], replicates, printdata,
lower, upper, x, reps);
setuptree(&curtree, nonodes2);
setuptree(&priortree, nonodes2);
setuptree(&bestree, nonodes2);
if (njumble > 1) setuptree(&bestree2, nonodes2);
}
for (i = 1; i <= spp; i++)
enterorder[i - 1] = i;
if (jumble)
randumize(seed, enterorder);
nextsp = 3;
buildsimpletree(&curtree, nextsp);
curtree.start = curtree.nodep[enterorder[0] - 1]->back;
if (jumb == 1) numtrees = 1;
nextsp = 4;
if (progress) {
printf("Adding species:\n");
writename(0, 3, enterorder);
#ifdef WIN32
phyFillScreenColor();
#endif
}
while (nextsp <= spp) {
nums = nextsp;
buildnewtip(enterorder[nextsp - 1], &curtree, nextsp);
copy_(&curtree, &priortree);
bestree.likelihood = -DBL_MAX;
curtree.start = curtree.nodep[enterorder[0] - 1]->back;
addtraverse(curtree.nodep[enterorder[nextsp - 1] - 1]->back,
curtree.start, true, &numtrees,&succeeded);
copy_(&bestree, &curtree);
if (progress) {
writename(nextsp - 1, 1, enterorder);
#ifdef WIN32
phyFillScreenColor();
#endif
}
if (global && nextsp == spp) {
if (progress) {
printf("Doing global rearrangements\n");
printf(" !");
for (j = spp; j < nonodes2; j++)
if ( (j - spp) % (( nonodes2 / 72 ) + 1 ) == 0 )
putchar('-');
printf("!\n");
printf(" ");
}
}
succeeded = true;
while (succeeded) {
succeeded = false;
curtree.start = curtree.nodep[enterorder[0] - 1]->back;
if (nextsp == spp && global)
globrearrange (&numtrees,&succeeded);
else{
rearrange(curtree.start,&numtrees,&nextsp,&succeeded);
}
if (global && ((nextsp) == spp) && progress)
printf("\n ");
}
if (global && nextsp == spp) {
putc('\n', outfile);
if (progress)
putchar('\n');
}
if (njumble > 1) {
if (jumb == 1 && nextsp == spp)
copy_(&bestree, &bestree2);
else if (nextsp == spp) {
if (bestree2.likelihood < bestree.likelihood)
copy_(&bestree, &bestree2);
}
}
if (nextsp == spp && jumb == njumble) {
if (njumble > 1) copy_(&bestree2, &curtree);
curtree.start = curtree.nodep[outgrno - 1]->back;
printree(curtree.start, treeprint, true, false);
summarize(numtrees);
}
nextsp++;
}
}
if (jumb == njumble && progress) {
printf("\nOutput written to file \"%s\"\n", outfilename);
if (trout) {
printf("\nTree also written onto file \"%s\"\n", outtreename);
}
}
} /* maketree */
int main(int argc, Char *argv[])
{
int i;
#ifdef MAC
argc = 1; /* macsetup("Fitch",""); */
argv[0]="Fitch";
#endif
init(argc,argv);
emboss_getoptions("ffitch",argc,argv);
progname = argv[0];
ibmpc = IBMCRT;
ansi = ANSICRT;
firstset = true;
doinit();
for (i=0;i 1) {
fprintf(outfile, "Data set # %ld:\n\n",ith);
if (progress)
printf("\nData set # %ld:\n\n",ith);
}
fitch_getinput();
for (jumb = 1; jumb <= njumble; jumb++)
maketree();
firstset = false;
}
if (trout)
FClose(outtree);
FClose(outfile);
FClose(infile);
#ifdef MAC
fixmacfile(outfilename);
fixmacfile(outtreename);
#endif
printf("\nDone.\n\n");
#ifdef WIN32
phyRestoreConsoleAttributes();
#endif
embExit();
return 0;
}
PHYLIPNEW-3.69.650/src/neighbor.c 0000664 0001750 0001750 00000032514 11305225544 013024 0000000 0000000
/* version 3.6. (c) Copyright 1993-2005 by the University of Washington.
Written by Mary Kuhner, Jon Yamato, Joseph Felsenstein, Akiko Fuseki,
Sean Lamont, and Andrew Keeffe.
Permission is granted to copy and use this program provided no fee is
charged for it and provided that this copyright notice is not removed. */
#include
#include "phylip.h"
#include "dist.h"
AjPPhyloDist* phylodists = NULL;
AjPPhyloTree* phylotrees;
#ifndef OLDC
/* function prototypes */
//void getoptions(void);
void emboss_getoptions(char *pgm, int argc, char *argv[]);
void allocrest(void);
void doinit(void);
void inputoptions(void);
void getinput(void);
void describe(node *, double);
void summarize(void);
void nodelabel(boolean);
void jointree(void);
void maketree(void);
void freerest(void);
/* function prototypes */
#endif
const char* outfilename;
const char* outtreename;
AjPFile embossoutfile;
AjPFile embossouttree;
Char infilename[FNMLNGTH];
long nonodes2, outgrno, col, datasets, ith;
long inseed;
vector *x;
intvector *reps;
boolean jumble, lower, upper, outgropt, replicates, trout,
printdata, progress, treeprint, mulsets, njoin;
tree curtree;
longer seed;
long *enterorder;
Char progname[20];
/* variables for maketree, propagated globally for C version: */
node **cluster;
void emboss_getoptions(char *pgm, int argc, char *argv[])
{
AjPStr matrixtype = NULL;
AjPStr treetype=NULL;
long inseed0 = 0;
putchar('\n');
jumble = false;
lower = false;
outgrno = 1;
outgropt = false;
replicates = false;
trout = true;
upper = false;
printdata = false;
progress = true;
treeprint = true;
njoin = true;
mulsets = false;
datasets = 1;
embInitPV(pgm, argc, argv, "PHYLIPNEW",VERSION);
matrixtype = ajAcdGetListSingle("matrixtype");
if(ajStrMatchC(matrixtype, "l")) lower = true;
else if(ajStrMatchC(matrixtype, "u")) upper = true;
phylodists = ajAcdGetDistances("datafile");
treetype = ajAcdGetListSingle("treetype");
if(ajStrMatchC(treetype, "n")) njoin = true;
else if(ajStrMatchC(treetype, "u")) njoin = false;
if(njoin) {
outgrno = ajAcdGetInt("outgrno");
if(outgrno != 0) outgropt = true;
else outgrno = 1;
}
replicates = ajAcdGetBoolean("replicates");
jumble = ajAcdGetToggle("jumble");
if(jumble) {
inseed = ajAcdGetInt("seed");
emboss_initseed(inseed, &inseed0, seed);
}
if((mulsets) && (!jumble)) {
jumble = true;
inseed = ajAcdGetInt("seed");
emboss_initseed(inseed, &inseed0, seed);
}
printdata = ajAcdGetBoolean("printdata");
progress = ajAcdGetBoolean("progress");
treeprint = ajAcdGetBoolean("treeprint");
trout = ajAcdGetToggle("trout");
embossoutfile = ajAcdGetOutfile("outfile");
embossouttree = ajAcdGetOutfile("outtreefile");
emboss_openfile(embossoutfile, &outfile, &outfilename);
if(trout) emboss_openfile(embossouttree, &outtree, &outtreename);
fprintf(outfile, "\nNeighbor-Joining/UPGMA method version %s\n\n",VERSION);
} /* emboss_getoptions */
void allocrest()
{
long i;
x = (vector *)Malloc(spp*sizeof(vector));
for (i = 0; i < spp; i++)
x[i] = (vector)Malloc(spp*sizeof(double));
reps = (intvector *)Malloc(spp*sizeof(intvector));
for (i = 0; i < spp; i++)
reps[i] = (intvector)Malloc(spp*sizeof(long));
nayme = (naym *)Malloc(spp*sizeof(naym));
enterorder = (long *)Malloc(spp*sizeof(long));
cluster = (node **)Malloc(spp*sizeof(node *));
} /* allocrest */
void freerest()
{
long i;
for (i = 0; i < spp; i++)
free(x[i]);
free(x);
for (i = 0; i < spp; i++)
free(reps[i]);
free(reps);
free(nayme);
free(enterorder);
free(cluster);
} /* freerest */
void doinit()
{
/* initializes variables */
node *p;
inputnumbers2seq(phylodists[0], &spp, &nonodes2, 2);
nonodes2 += (njoin ? 0 : 1);
alloctree(&curtree.nodep, nonodes2+1);
p = curtree.nodep[nonodes2]->next;
curtree.nodep[nonodes2]->next = curtree.nodep[nonodes2];
free(p->next);
free(p);
allocrest();
} /* doinit */
void inputoptions()
{
/* read options information */
if (ith != 1)
samenumspseq2(phylodists[ith-1], ith);
putc('\n', outfile);
if (njoin)
fprintf(outfile, " Neighbor-joining method\n");
else
fprintf(outfile, " UPGMA method\n");
fprintf(outfile, "\n Negative branch lengths allowed\n\n");
} /* inputoptions */
void describe(node *p, double height)
{
/* print out information for one branch */
long i;
node *q;
q = p->back;
if (njoin)
fprintf(outfile, "%4ld ", q->index - spp);
else
fprintf(outfile, "%4ld ", q->index - spp);
if (p->tip) {
for (i = 0; i < nmlngth; i++)
putc(nayme[p->index - 1][i], outfile);
putc(' ', outfile);
} else {
if (njoin)
fprintf(outfile, "%4ld ", p->index - spp);
else {
fprintf(outfile, "%4ld ", p->index - spp);
}
}
if (njoin)
fprintf(outfile, "%12.5f\n", q->v);
else
fprintf(outfile, "%10.5f %10.5f\n", q->v, q->v+height);
if (!p->tip) {
describe(p->next->back, height+q->v);
describe(p->next->next->back, height+q->v);
}
} /* describe */
void summarize()
{
/* print out branch lengths etc. */
putc('\n', outfile);
if (njoin) {
fprintf(outfile, "remember:");
if (outgropt)
fprintf(outfile, " (although rooted by outgroup)");
fprintf(outfile, " this is an unrooted tree!\n");
}
if (njoin) {
fprintf(outfile, "\nBetween And Length\n");
fprintf(outfile, "------- --- ------\n");
} else {
fprintf(outfile, "From To Length Height\n");
fprintf(outfile, "---- -- ------ ------\n");
}
describe(curtree.start->next->back, 0.0);
describe(curtree.start->next->next->back, 0.0);
if (njoin)
describe(curtree.start->back, 0.0);
fprintf(outfile, "\n\n");
} /* summarize */
void nodelabel(boolean isnode)
{
if (isnode)
printf("node");
else
printf("species");
} /* nodelabel */
void jointree()
{
/* calculate the tree */
long nc, nextnode, mini=0, minj=0, i, j, ia, ja, ii, jj, nude, iter;
double fotu2, total, tmin, dio, djo, bi, bj, bk, dmin=0, da;
long el[3];
vector av;
intvector oc;
double *R; /* added in revisions by Y. Ina */
R = (double *)Malloc(spp * sizeof(double));
for (i = 0; i <= spp - 2; i++) {
for (j = i + 1; j < spp; j++) {
da = (x[i][j] + x[j][i]) / 2.0;
x[i][j] = da;
x[j][i] = da;
}
}
/* First initialization */
fotu2 = spp - 2.0;
nextnode = spp + 1;
av = (vector)Malloc(spp*sizeof(double));
oc = (intvector)Malloc(spp*sizeof(long));
for (i = 0; i < spp; i++) {
av[i] = 0.0;
oc[i] = 1;
}
/* Enter the main cycle */
if (njoin)
iter = spp - 3;
else
iter = spp - 1;
for (nc = 1; nc <= iter; nc++) {
for (j = 2; j <= spp; j++) {
for (i = 0; i <= j - 2; i++)
x[j - 1][i] = x[i][j - 1];
}
tmin = DBL_MAX;
/* Compute sij and minimize */
if (njoin) { /* many revisions by Y. Ina from here ... */
for (i = 0; i < spp; i++)
R[i] = 0.0;
for (ja = 2; ja <= spp; ja++) {
jj = enterorder[ja - 1];
if (cluster[jj - 1] != NULL) {
for (ia = 0; ia <= ja - 2; ia++) {
ii = enterorder[ia];
if (cluster[ii - 1] != NULL) {
R[ii - 1] += x[ii - 1][jj - 1];
R[jj - 1] += x[ii - 1][jj - 1];
}
}
}
}
} /* ... to here */
for (ja = 2; ja <= spp; ja++) {
jj = enterorder[ja - 1];
if (cluster[jj - 1] != NULL) {
for (ia = 0; ia <= ja - 2; ia++) {
ii = enterorder[ia];
if (cluster[ii - 1] != NULL) {
if (njoin) {
total = fotu2 * x[ii - 1][jj - 1] - R[ii - 1] - R[jj - 1];
/* this statement part of revisions by Y. Ina */
} else
total = x[ii - 1][jj - 1];
if (total < tmin) {
tmin = total;
mini = ii;
minj = jj;
}
}
}
}
}
/* compute lengths and print */
if (njoin) {
dio = 0.0;
djo = 0.0;
for (i = 0; i < spp; i++) {
dio += x[i][mini - 1];
djo += x[i][minj - 1];
}
dmin = x[mini - 1][minj - 1];
dio = (dio - dmin) / fotu2;
djo = (djo - dmin) / fotu2;
bi = (dmin + dio - djo) * 0.5;
bj = dmin - bi;
bi -= av[mini - 1];
bj -= av[minj - 1];
} else {
bi = x[mini - 1][minj - 1] / 2.0 - av[mini - 1];
bj = x[mini - 1][minj - 1] / 2.0 - av[minj - 1];
av[mini - 1] += bi;
}
if (progress) {
printf("Cycle %3ld: ", iter - nc + 1);
if (njoin)
nodelabel((boolean)(av[mini - 1] > 0.0));
else
nodelabel((boolean)(oc[mini - 1] > 1.0));
printf(" %ld (%10.5f) joins ", mini, bi);
if (njoin)
nodelabel((boolean)(av[minj - 1] > 0.0));
else
nodelabel((boolean)(oc[minj - 1] > 1.0));
printf(" %ld (%10.5f)\n", minj, bj);
#ifdef WIN32
phyFillScreenColor();
#endif
}
hookup(curtree.nodep[nextnode - 1]->next, cluster[mini - 1]);
hookup(curtree.nodep[nextnode - 1]->next->next, cluster[minj - 1]);
cluster[mini - 1]->v = bi;
cluster[minj - 1]->v = bj;
cluster[mini - 1]->back->v = bi;
cluster[minj - 1]->back->v = bj;
cluster[mini - 1] = curtree.nodep[nextnode - 1];
cluster[minj - 1] = NULL;
nextnode++;
if (njoin)
av[mini - 1] = dmin * 0.5;
/* re-initialization */
fotu2 -= 1.0;
for (j = 0; j < spp; j++) {
if (cluster[j] != NULL) {
if (njoin) {
da = (x[mini - 1][j] + x[minj - 1][j]) * 0.5;
if (mini - j - 1 < 0)
x[mini - 1][j] = da;
if (mini - j - 1 > 0)
x[j][mini - 1] = da;
} else {
da = x[mini - 1][j] * oc[mini - 1] + x[minj - 1][j] * oc[minj - 1];
da /= oc[mini - 1] + oc[minj - 1];
x[mini - 1][j] = da;
x[j][mini - 1] = da;
}
}
}
for (j = 0; j < spp; j++) {
x[minj - 1][j] = 0.0;
x[j][minj - 1] = 0.0;
}
oc[mini - 1] += oc[minj - 1];
}
/* the last cycle */
nude = 1;
for (i = 1; i <= spp; i++) {
if (cluster[i - 1] != NULL) {
el[nude - 1] = i;
nude++;
}
}
if (!njoin) {
curtree.start = cluster[el[0] - 1];
curtree.start->back = NULL;
free(av);
free(oc);
return;
}
bi = (x[el[0] - 1][el[1] - 1] + x[el[0] - 1][el[2] - 1] - x[el[1] - 1]
[el[2] - 1]) * 0.5;
bj = x[el[0] - 1][el[1] - 1] - bi;
bk = x[el[0] - 1][el[2] - 1] - bi;
bi -= av[el[0] - 1];
bj -= av[el[1] - 1];
bk -= av[el[2] - 1];
if (progress) {
printf("last cycle:\n");
putchar(' ');
nodelabel((boolean)(av[el[0] - 1] > 0.0));
printf(" %ld (%10.5f) joins ", el[0], bi);
nodelabel((boolean)(av[el[1] - 1] > 0.0));
printf(" %ld (%10.5f) joins ", el[1], bj);
nodelabel((boolean)(av[el[2] - 1] > 0.0));
printf(" %ld (%10.5f)\n", el[2], bk);
#ifdef WIN32
phyFillScreenColor();
#endif
}
hookup(curtree.nodep[nextnode - 1], cluster[el[0] - 1]);
hookup(curtree.nodep[nextnode - 1]->next, cluster[el[1] - 1]);
hookup(curtree.nodep[nextnode - 1]->next->next, cluster[el[2] - 1]);
cluster[el[0] - 1]->v = bi;
cluster[el[1] - 1]->v = bj;
cluster[el[2] - 1]->v = bk;
cluster[el[0] - 1]->back->v = bi;
cluster[el[1] - 1]->back->v = bj;
cluster[el[2] - 1]->back->v = bk;
curtree.start = cluster[el[0] - 1]->back;
free(av);
free(oc);
} /* jointree */
void maketree()
{
/* construct the tree */
long i ;
dist_inputdata(phylodists[ith-1], replicates, printdata,
lower, upper, x, reps);
if (njoin && (spp < 3)) {
printf("\nERROR: Neighbor-Joining runs must have at least 3 species\n\n");
embExitBad();
}
if (progress)
putchar('\n');
if (ith == 1)
setuptree(&curtree, nonodes2 + 1);
for (i = 1; i <= spp; i++)
enterorder[i - 1] = i;
if (jumble)
randumize(seed, enterorder);
for (i = 0; i < spp; i++)
cluster[i] = curtree.nodep[i];
jointree();
if (njoin)
curtree.start = curtree.nodep[outgrno - 1]->back;
printree(curtree.start, treeprint, njoin, (boolean)(!njoin));
if (treeprint)
summarize();
if (trout) {
col = 0;
if (njoin)
treeout(curtree.start, &col, 0.43429448222, njoin, curtree.start);
else
curtree.root = curtree.start,
treeoutr(curtree.start,&col,&curtree);
}
if (progress) {
printf("\nOutput written on file \"%s\"\n\n", outfilename);
if (trout)
printf("Tree written on file \"%s\"\n\n", outtreename);
}
} /* maketree */
int main(int argc, Char *argv[])
{ /* main program */
#ifdef MAC
argc = 1; /* macsetup("Neighbor",""); */
argv[0] = "Neighbor";
#endif
init(argc, argv);
emboss_getoptions("fneighbor",argc,argv);
ibmpc = IBMCRT;
ansi = ANSICRT;
doinit();
ith = 1;
while (phylodists[ith-1]) {
if (ith > 1) {
fprintf(outfile, "Data set # %ld:\n",ith);
if (progress)
printf("Data set # %ld:\n",ith);
}
inputoptions();
maketree();
ith++;
}
FClose(infile);
FClose(outfile);
FClose(outtree);
freerest();
freetree(&curtree.nodep, nonodes2+1);
#ifdef MAC
fixmacfile(outfilename);
fixmacfile(outtreename);
#endif
printf("Done.\n\n");
#ifdef WIN32
phyRestoreConsoleAttributes();
#endif
embExit();
return 0;
}
PHYLIPNEW-3.69.650/src/mix.c 0000664 0001750 0001750 00000064633 11305225544 012033 0000000 0000000
#include "phylip.h"
#include "disc.h"
#include "wagner.h"
/* version 3.6. (c) Copyright 1993-2004 by the University of Washington.
Written by Joseph Felsenstein, Akiko Fuseki, Sean Lamont, and Andrew Keeffe.
Permission is granted to copy and use this program provided no fee is
charged for it and provided that this copyright notice is not removed. */
#define maxtrees 100 /* maximum number of tied trees stored */
typedef long *placeptr;
AjPPhyloState* phylostates = NULL;
AjPPhyloProp phyloweights = NULL;
AjPPhyloProp phyloanc = NULL;
AjPPhyloProp phylomix = NULL;
AjPPhyloTree* phylotrees = NULL;
#ifndef OLDC
/* function prototypes */
//void getoptions(void);
void emboss_getoptions(char *pgm, int argc, char *argv[]);
void allocrest(void);
void doinit(void);
void inputoptions(void);
void doinput(void);
void evaluate(node2 *);
void reroot(node2 *);
void savetraverse(node2 *);
void savetree(void);
void mix_addtree(long *pos);
void mix_findtree(boolean *, long *, long, long *, long **);
void tryadd(node2 *, node2 **, node2 **);
void addpreorder(node2 *, node2 *, node2 *);
void tryrearr(node2 *, node2 **, boolean *);
void repreorder(node2 *, node2 **, boolean *);
void rearrange(node2 **r);
void mix_addelement(node2 **, long *, long *, boolean *, char**);
void mix_treeread(void);
void describe(void);
void maketree(void);
void reallocchars(void);
/* function prototypes */
#endif
Char infilename[FNMLNGTH], intreename[FNMLNGTH], weightfilename[FNMLNGTH], ancfilename[FNMLNGTH], mixfilename[FNMLNGTH];
const char* outfilename;
const char* outtreename;
AjPFile embossoutfile;
AjPFile embossouttree;
node2 *root;
long outgrno, msets, ith, njumble, jumb, numtrees;
/* outgrno indicates outgroup */
long inseed, inseed0;
boolean jumble, usertree, weights, ancvar, questions, allsokal,
allwagner, mixture, trout, noroot, outgropt, didreroot,
progress, treeprint, stepbox, ancseq, mulsets, firstset,
justwts;
boolean *ancone, *anczero, *ancone0, *anczero0;
pointptr2 treenode; /* pointers to all nodes in tree */
double threshold;
double *threshwt;
bitptr wagner, wagner0;
longer seed;
long *enterorder;
double **fsteps;
char *guess;
long **bestrees;
steptr numsteps, numsone, numszero;
gbit *garbage;
char ch;
char *progname;
/* Local variables for maketree: */
long minwhich;
double like, bestyet, bestlike, bstlike2, minsteps;
boolean lastrearr,full;
double nsteps[maxuser];
node2 *there;
long fullset;
bitptr steps, zeroanc, oneanc, fulzeroanc, empzeroanc;
long *place, col;
void emboss_getoptions(char *pgm, int argc, char *argv[])
{
AjPStr method = NULL;
ajint numseqs=0;
ajint numwts=0;
jumble = false;
njumble = 1;
outgrno = 1;
outgropt = false;
trout = true;
usertree = false;
weights = false;
justwts = false;
ancvar = false;
allsokal = false;
allwagner = false;
mixture = false;
printdata = false;
progress = true;
treeprint = true;
stepbox = false;
ancseq = false;
mulsets = false;
msets = 1;
embInitPV(pgm, argc, argv, "PHYLIPNEW",VERSION);
phylostates = ajAcdGetDiscretestates("infile");
while (phylostates[numseqs])
numseqs++;
phyloweights = ajAcdGetProperties("weights");
if (phyloweights)
{
weights = true;
numwts = ajPhyloPropGetSize(phyloweights);
}
if (numseqs > 1) {
mulsets = true;
msets = numseqs;
}
else if (numwts > 1) {
mulsets = true;
msets = numwts;
justwts = true;
}
phyloanc = ajAcdGetProperties("ancfile");
if(phyloanc) ancvar = true;
phylotrees = ajAcdGetTree("intreefile");
if (phylotrees)
{
while (phylotrees[numtrees])
numtrees++;
usertree = true;
}
method = ajAcdGetListSingle("method");
if(ajStrMatchC(method, "w")) allwagner = true;
else if(ajStrMatchC(method, "c")) allsokal = true;
else if(ajStrMatchC(method, "m")) {
mixture = allwagner = true;
phylomix = ajAcdGetProperties("mixfile");
}
if(!usertree) {
njumble = ajAcdGetInt("njumble");
if(njumble >0) {
inseed = ajAcdGetInt("seed");
jumble = true;
emboss_initseed(inseed, &inseed0, seed);
}
else njumble = 1;
}
outgrno = ajAcdGetInt("outgrno");
if(outgrno != 0) outgropt = true;
else outgrno = 1;
threshold = ajAcdGetFloat("threshold");
printdata = ajAcdGetBoolean("printdata");
progress = ajAcdGetBoolean("progress");
treeprint = ajAcdGetBoolean("treeprint");
trout = ajAcdGetToggle("trout");
stepbox = ajAcdGetBoolean("stepbox");
ancseq = ajAcdGetBoolean("ancseq");
embossoutfile = ajAcdGetOutfile("outfile");
emboss_openfile(embossoutfile, &outfile, &outfilename);
if(trout) {
embossouttree = ajAcdGetOutfile("outtreefile");
emboss_openfile(embossouttree, &outtree, &outtreename);
}
fprintf(outfile, "\nMixed parsimony algorithm, version %s\n\n",VERSION);
} /* emboss_getoptions */
void reallocchars()
{
long i;
if (usertree) {
for (i = 0; i < maxuser; i++) {
free (fsteps[i]);
fsteps[i] = (double *)Malloc(chars*sizeof(double));
}
}
free(extras);
free(weight);
free(threshwt);
free(numsteps);
free(numszero);
free(numsone);
free(guess);
free(ancone);
free(anczero);
free(ancone0);
free(anczero0);
extras = (steptr)Malloc(chars*sizeof(long));
weight = (steptr)Malloc(chars*sizeof(long));
threshwt = (double *)Malloc(chars*sizeof(double));
numsteps = (steptr)Malloc(chars*sizeof(long));
numszero = (steptr)Malloc(chars*sizeof(long));
numsone = (steptr)Malloc(chars*sizeof(long));
guess = (Char *)Malloc(chars*sizeof(Char));
ancone = (boolean *)Malloc(chars*sizeof(boolean));
anczero = (boolean *)Malloc(chars*sizeof(boolean));
ancone0 = (boolean *)Malloc(chars*sizeof(boolean));
anczero0 = (boolean *)Malloc(chars*sizeof(boolean));
}
void allocrest()
{
long i;
if (usertree) {
fsteps = (double **)Malloc(maxuser*sizeof(double *));
for (i = 0; i < maxuser; i++)
fsteps[i] = (double *)Malloc(chars*sizeof(double));
}
bestrees = (long **)Malloc(maxtrees*sizeof(long *));
for (i = 1; i <= maxtrees; i++)
bestrees[i - 1] = (long *)Malloc((spp+1)*sizeof(long));
extras = (steptr)Malloc(chars*sizeof(long));
weight = (steptr)Malloc(chars*sizeof(long));
threshwt = (double *)Malloc(chars*sizeof(double));
numsteps = (steptr)Malloc(chars*sizeof(long));
numszero = (steptr)Malloc(chars*sizeof(long));
numsone = (steptr)Malloc(chars*sizeof(long));
guess = (Char *)Malloc(chars*sizeof(Char));
nayme = (naym *)Malloc(spp*sizeof(naym));
enterorder = (long *)Malloc(spp*sizeof(long));
ancone = (boolean *)Malloc(chars*sizeof(boolean));
anczero = (boolean *)Malloc(chars*sizeof(boolean));
ancone0 = (boolean *)Malloc(chars*sizeof(boolean));
anczero0 = (boolean *)Malloc(chars*sizeof(boolean));
wagner = (bitptr)Malloc(words*sizeof(long));
wagner0 = (bitptr)Malloc(words*sizeof(long));
place = (long *)Malloc(nonodes*sizeof(long));
steps = (bitptr)Malloc(words*sizeof(long));
zeroanc = (bitptr)Malloc(words*sizeof(long));
oneanc = (bitptr)Malloc(words*sizeof(long));
fulzeroanc = (bitptr)Malloc(words*sizeof(long));
empzeroanc = (bitptr)Malloc(words*sizeof(long));
} /* allocrest */
void doinit()
{
/* initializes variables */
inputnumbersstate(phylostates[0], &spp, &chars, &nonodes, 1);
words = chars / bits + 1;
if (printdata)
fprintf(outfile, "%ld species, %ld characters\n\n", spp, chars);
alloctree2(&treenode);
setuptree2(treenode);
allocrest();
} /* doinit */
void inputoptions()
{
/* input the information on the options */
long i;
if(justwts){
if(firstset){
if (ancvar)
inputancestorsstr(phyloanc->Str[0], anczero0, ancone0);
if (mixture)
inputmixturestr(phylomix->Str[0], wagner0);
}
for (i = 0; i < (chars); i++)
weight[i] = 1;
inputweightsstr(phyloweights->Str[0], chars, weight, &weights);
for (i = 0; i < (words); i++) {
if (mixture)
wagner[i] = wagner0[i];
else if (allsokal)
wagner[i] = 0;
else
wagner[i] = (1L << (bits + 1)) - (1L << 1);
}
}
else {
if (!firstset) {
samenumspstate(phylostates[ith-1], &chars, ith);
reallocchars();
}
for (i = 0; i < (chars); i++)
weight[i] = 1;
if (ancvar)
inputancestorsstr(phyloanc->Str[0], anczero0, ancone0);
if (mixture)
inputmixturestr(phylomix->Str[0], wagner0);
if (weights)
inputweightsstr(phyloweights->Str[0], chars, weight, &weights);
for (i = 0; i < (words); i++) {
if (mixture)
wagner[i] = wagner0[i];
else if (allsokal)
wagner[i] = 0;
else
wagner[i] = (1L << (bits + 1)) - (1L << 1);
}
}
for (i = 0; i < (chars); i++) {
if (!ancvar) {
anczero[i] = true;
ancone[i] = (((1L << (i % bits + 1)) & wagner[i / bits]) != 0);
} else {
anczero[i] = anczero0[i];
ancone[i] = ancone0[i];
}
}
noroot = true;
questions = false;
for (i = 0; i < (chars); i++) {
if (weight[i] > 0) {
noroot = (noroot && ancone[i] && anczero[i] &&
((((1L << (i % bits + 1)) & wagner[i / bits]) != 0)
|| threshold <= 2.0));
}
questions = (questions || (ancone[i] && anczero[i]));
threshwt[i] = threshold * weight[i];
}
} /* inputoptions */
void doinput()
{
/* reads the input data */
inputoptions();
if(!justwts || firstset)
disc_inputdata2(phylostates[ith-1], treenode);
} /* doinput */
void evaluate(node2 *r)
{
/* Determines the number of steps needed for a tree.
This is the minimum number needed to evolve chars on
this tree */
long i, stepnum, smaller;
double sum, term;
sum = 0.0;
for (i = 0; i < (chars); i++) {
numszero[i] = 0;
numsone[i] = 0;
}
full = true;
for (i = 0; i < (words); i++)
zeroanc[i] = fullset;
postorder(r, fullset, full, wagner, zeroanc);
cpostorder(r, full, zeroanc, numszero, numsone);
count(r->fulstte1, zeroanc, numszero, numsone);
for (i = 0; i < (words); i++)
zeroanc[i] = 0;
full = false;
postorder(r, fullset, full, wagner, zeroanc);
cpostorder(r, full, zeroanc, numszero, numsone);
count(r->empstte0, zeroanc, numszero, numsone);
for (i = 0; i < (chars); i++) {
smaller = spp * weight[i];
numsteps[i] = smaller;
if (anczero[i]) {
numsteps[i] = numszero[i];
smaller = numszero[i];
}
if (ancone[i] && numsone[i] < smaller)
numsteps[i] = numsone[i];
stepnum = numsteps[i] + extras[i];
if (stepnum <= threshwt[i])
term = stepnum;
else
term = threshwt[i];
sum += term;
if (usertree && which <= maxuser)
fsteps[which - 1][i] = term;
guess[i] = '?';
if (!ancone[i] || (anczero[i] && numszero[i] < numsone[i]))
guess[i] = '0';
else if (!anczero[i] || (ancone[i] && numsone[i] < numszero[i]))
guess[i] = '1';
}
if (usertree && which <= maxuser) {
nsteps[which - 1] = sum;
if (which == 1) {
minwhich = 1;
minsteps = sum;
} else if (sum < minsteps) {
minwhich = which;
minsteps = sum;
}
}
like = -sum;
} /* evaluate */
void reroot(node2 *outgroup)
{
/* reorients tree, putting outgroup in desired position. */
node2 *p, *q;
if (outgroup->back->index == root->index)
return;
p = root->next;
q = root->next->next;
p->back->back = q->back;
q->back->back = p->back;
p->back = outgroup;
q->back = outgroup->back;
outgroup->back->back = q;
outgroup->back = p;
} /* reroot */
void savetraverse(node2 *p)
{
/* sets BOOLEANs that indicate which way is down */
p->bottom = true;
if (p->tip)
return;
p->next->bottom = false;
savetraverse(p->next->back);
p->next->next->bottom = false;
savetraverse(p->next->next->back);
} /* savetraverse */
void savetree()
{
/* record in place where each species has to be
added to reconstruct this tree */
long i, j;
node2 *p;
boolean done;
if (noroot)
reroot(treenode[outgrno - 1]);
savetraverse(root);
for (i = 0; i < (nonodes); i++)
place[i] = 0;
place[root->index - 1] = 1;
for (i = 1; i <= (spp); i++) {
p = treenode[i - 1];
while (place[p->index - 1] == 0) {
place[p->index - 1] = i;
while (!p->bottom)
p = p->next;
p = p->back;
}
if (i > 1) {
place[i - 1] = place[p->index - 1];
j = place[p->index - 1];
done = false;
while (!done) {
place[p->index - 1] = spp + i - 1;
while (!p->bottom)
p = p->next;
p = p->back;
done = (p == NULL);
if (!done)
done = (place[p->index - 1] != j);
}
}
}
} /* savetree */
void mix_addtree(long *pos)
{
/* puts tree from ARRAY place in its proper position
in ARRAY bestrees */
long i;
for (i =nextree - 1; i >= (*pos); i--)
memcpy(bestrees[i], bestrees[i - 1], spp*sizeof(long));
for (i = 0; i < (spp); i++)
bestrees[(*pos) - 1][i] = place[i];
nextree++;
} /* mix_addtree */
void mix_findtree(boolean *found, long *pos, long nextree,
long *place, long **bestrees)
{
/* finds tree given by ARRAY place in ARRAY bestrees by binary search */
/* used by dnacomp, dnapars, dollop, mix, & protpars */
long i, lower, upper;
boolean below, done;
below = false;
lower = 1;
upper = nextree - 1;
(*found) = false;
while (!(*found) && lower <= upper) {
(*pos) = (lower + upper) / 2;
i = 3;
done = false;
while (!done) {
done = (i > spp);
if (!done)
done = (place[i - 1] != bestrees[(*pos) - 1][i - 1]);
if (!done)
i++;
}
(*found) = (i > spp);
below = (place[i - 1] < bestrees[(*pos )- 1][i - 1]);
if (*found)
break;
if (below)
upper = (*pos) - 1;
else
lower = (*pos) + 1;
}
if (!(*found) && !below)
(*pos)++;
} /* mix_findtree */
void tryadd(node2 *p, node2 **item, node2 **nufork)
{
/* temporarily adds one fork and one tip to the tree.
if the location where they are added yields greater
"likelihood" than other locations tested up to that
time, then keeps that location as there */
long pos;
boolean found;
node2 *rute;
add3(p, *item, *nufork, &root, treenode);
evaluate(root);
if (lastrearr) {
if (like >= bstlike2) {
rute = root->next->back;
savetree();
reroot(rute);
if (like > bstlike2) {
bestlike = bstlike2 = like;
pos = 1;
nextree = 1;
mix_addtree(&pos);
} else {
pos = 0;
mix_findtree(&found, &pos, nextree, place, bestrees);
if (!found) {
if (nextree <= maxtrees)
mix_addtree(&pos);
}
}
}
}
if (like > bestyet) {
bestyet = like;
there = p;
}
re_move3(item, nufork, &root, treenode);
} /* tryadd */
void addpreorder(node2 *p, node2 *item, node2 *nufork)
{
/* traverses a binary tree, calling PROCEDURE tryadd
at a node before calling tryadd at its descendants */
if (p == NULL)
return;
tryadd(p, &item, &nufork);
if (!p->tip) {
addpreorder(p->next->back, item, nufork);
addpreorder(p->next->next->back, item, nufork);
}
} /* addpreorder */
void tryrearr(node2 *p, node2 **r, boolean *success)
{
/* evaluates one rearrangement of the tree.
if the new tree has greater "likelihood" than the old
one sets success := TRUE and keeps the new tree.
otherwise, restores the old tree */
node2 *frombelow, *whereto, *forknode;
double oldlike;
if (p->back == NULL)
return;
forknode = treenode[p->back->index - 1];
if (forknode->back == NULL)
return;
oldlike = bestyet;
if (p->back->next->next == forknode)
frombelow = forknode->next->next->back;
else
frombelow = forknode->next->back;
whereto = treenode[forknode->back->index - 1];
re_move3(&p, &forknode, &root, treenode);
add3(whereto, p, forknode, &root, treenode);
evaluate(*r);
if ( like - oldlike > LIKE_EPSILON ) {
*success = true;
bestyet = like;
} else {
re_move3(&p, &forknode, &root, treenode);
add3(frombelow, p, forknode, &root, treenode);
}
} /* tryrearr */
void repreorder(node2 *p, node2 **r, boolean *success)
{
/* traverses a binary tree, calling PROCEDURE tryrearr
at a node before calling tryrearr at its descendants */
if (p == NULL)
return;
tryrearr(p, r, success);
if (!p->tip) {
repreorder(p->next->back, r,success);
repreorder(p->next->next->back, r,success);
}
} /* repreorder */
void rearrange(node2 **r)
{
/* traverses the tree (preorder), finding any local
rearrangement which decreases the number of steps.
if traversal succeeds in increasing the tree's
"likelihood", PROCEDURE rearrange runs traversal again */
boolean success=true;
while (success) {
success = false;
repreorder(*r,r,&success);
}
} /* rearrange */
void mix_addelement(node2 **p, long *nextnode, long *lparens,
boolean *names, char** treestr)
{
/* recursive procedure adds nodes to user-defined tree */
node2 *q;
long i, n;
boolean found;
Char str[nmlngth];
sgetch(&ch, lparens, treestr);
if (ch == '(' ) {
if ((*lparens) >= spp) {
printf("\n\nERROR IN USER TREE: Too many left parentheses\n\n");
embExitBad();
}
(*nextnode)++;
q = treenode[(*nextnode) - 1];
mix_addelement(&q->next->back, nextnode, lparens, names, treestr);
q->next->back->back = q->next;
do {
ch = *(*treestr)++;
} while (ch && ch != ',');
mix_addelement(&q->next->next->back, nextnode, lparens, names, treestr);
q->next->next->back->back = q->next->next;
do {
ch = *(*treestr)++;
} while (ch && ch != ')');
*p = q;
return;
}
for (i = 0; i < nmlngth; i++)
str[i] = ' ';
n = 1;
do {
if (ch == '_')
ch = ' ';
str[n - 1] =ch;
ch = *(*treestr)++ ;
n++;
} while (ch != ',' && ch != ')' && ch != ':' && n <= nmlngth);
n = 1;
do {
found = true;
for (i = 0; i < nmlngth; i++)
found = (found && ((str[i] == nayme[n - 1][i]) ||
((nayme[n - 1][i] == '_') && (str[i] == ' '))));
if (found) {
if (names[n - 1] == false) {
*p = treenode[n - 1];
names[n - 1] = true;
} else {
printf("\n\nERROR IN USER TREE: Duplicate name found: ");
for (i = 0; i < nmlngth; i++)
putchar(nayme[n - 1][i]);
printf("\n\n");
embExitBad();
}
} else
n++;
} while (!(n > spp || found ));
if (n <= spp)
return;
printf("CANNOT FIND SPECIES: ");
for (i = 0; i < nmlngth; i++)
putchar(str[i]);
putchar('\n');
} /* mix_addelement */
void mix_treeread()
{
/* read in user-defined tree and set it up */
long nextnode, lparens, i;
boolean *names;
char* treestr;
root = treenode[spp];
nextnode = spp;
root->back = NULL;
names = (boolean *)Malloc(spp*sizeof(boolean));
for (i = 0; i < (spp); i++)
names[i] = false;
lparens = 0;
treestr = ajStrGetuniquePtr(&phylotrees[0]->Tree);
mix_addelement(&root, &nextnode, &lparens, names, &treestr);
if (ch == '[') {
do
ch = *treestr++;
while (ch != ']');
ch = *treestr++;
}
do {
ch = *treestr++;
} while (ch && ch != ';');
if (progress)
printf(".");
free(names);
} /* mix_treeread */
void describe()
{
/* prints ancestors, steps and table of numbers of steps in
each character */
if (treeprint)
fprintf(outfile, "\nrequires a total of %10.3f\n", -like);
putc('\n', outfile);
if (stepbox)
writesteps(weights, numsteps);
if (questions && (!noroot || didreroot))
guesstates(guess);
if (ancseq) {
hypstates(fullset, full, noroot, didreroot, root, wagner,
zeroanc, oneanc, treenode, guess, garbage);
putc('\n', outfile);
}
putc('\n', outfile);
if (trout) {
col = 0;
treeout2(root, &col, root);
}
} /* describe */
void maketree()
{
/* constructs a binary tree from the pointers in treenode.
adds each node at location which yields highest "likelihood"
then rearranges the tree for greatest "likelihood" */
long i, j;
double gotlike;
node2 *item, *nufork, *dummy;
fullset = (1L << (bits + 1)) - (1L << 1);
for (i=0 ; i gotlike);
}
}
if (progress)
putchar('\n');
for (i = spp - 1; i >= 1; i--)
re_move3(&treenode[i], &dummy, &root, treenode);
if (jumb == njumble) {
if (treeprint) {
putc('\n', outfile);
if (nextree == 2)
fprintf(outfile, "One most parsimonious tree found:\n");
else
fprintf(outfile, "%6ld trees in all found\n", nextree - 1);
}
if (nextree > maxtrees + 1) {
if (treeprint)
fprintf(outfile, "here are the first%4ld of them\n",(long)maxtrees);
nextree = maxtrees + 1;
}
if (treeprint)
putc('\n', outfile);
for (i = 0; i <= (nextree - 2); i++) {
root = treenode[0];
add3(treenode[0], treenode[1], treenode[spp], &root, treenode);
for (j = 3; j <= (spp); j++)
add3(treenode[bestrees[i][j - 1] - 1], treenode[j - 1],
treenode[spp + j - 2], &root, treenode);
if (noroot)
reroot(treenode[outgrno - 1]);
didreroot = (outgropt && noroot);
evaluate(root);
printree(treeprint, noroot, didreroot, root);
describe();
for (j = 1; j < (spp); j++)
re_move3(&treenode[j], &dummy, &root, treenode);
}
}
} else {
if (numtrees > 2)
emboss_initseed(inseed, &inseed0, seed);
if (treeprint) {
fprintf(outfile, "User-defined tree");
if (numtrees > 1)
putc('s', outfile);
fprintf(outfile, ":\n\n");
}
which = 1;
if (progress)
printf(" ");
while (which <= numtrees ) {
mix_treeread();
didreroot = (outgropt && noroot);
if (noroot)
reroot(treenode[outgrno - 1]);
evaluate(root);
printree(treeprint, noroot, didreroot, root);
describe();
which++;
}
if (progress)
printf("\n");
FClose(intree);
fprintf(outfile, "\n\n");
if (numtrees > 2 && chars > 1 ) {
if (progress)
printf(" sampling for SH test\n");
standev(numtrees, minwhich, minsteps, nsteps, fsteps, seed);
}
}
if (jumb == njumble) {
if (progress) {
printf("\nOutput written to file \"%s\"\n", outfilename);
if (trout)
printf("\nTrees also written onto file \"%s\"\n", outtreename);
putchar('\n');
}
}
if (ancseq)
freegarbage(&garbage);
} /* maketree */
int main(int argc, Char *argv[])
{ /* Mixed parsimony by uphill search */
#ifdef MAC
argc = 1; /* macsetup("Mix",""); */
argv[0] = "Mix";
#endif
init(argc, argv);
emboss_getoptions("fmix",argc,argv);
progname = argv[0];
ibmpc = IBMCRT;
ansi = ANSICRT;
firstset = true;
garbage = NULL;
bits = 8*sizeof(long) - 1;
doinit();
for (ith = 1; ith <= msets; ith++) {
if(firstset){
if (allsokal && !mixture)
fprintf(outfile, "Camin-Sokal parsimony method\n\n");
if (allwagner && !mixture)
fprintf(outfile, "Wagner parsimony method\n\n");
if (mixture)
fprintf(outfile, "Mixture of Wagner and Camin-Sokal parsimony methods\n\n");
}
doinput();
if (msets > 1 && !justwts) {
fprintf(outfile, "Data set # %ld:\n\n",ith);
if (progress)
printf("\nData set # %ld:\n",ith);
}
if (justwts){
if(firstset && mixture && (printdata || stepbox || ancseq))
printmixture(outfile, wagner);
fprintf(outfile, "Weights set # %ld:\n\n", ith);
if (progress)
printf("\nWeights set # %ld:\n\n", ith);
}
else if (mixture && (printdata || stepbox || ancseq))
printmixture(outfile, wagner);
if (printdata){
if (weights || justwts)
printweights(outfile, 0, chars, weight, "Characters");
if (ancvar)
printancestors(outfile, anczero, ancone);
}
if (ith == 1)
firstset = false;
for (jumb = 1; jumb <= njumble; jumb++)
maketree();
}
free(place);
free(steps);
free(zeroanc);
free(oneanc);
free(fulzeroanc);
free(empzeroanc);
FClose(outfile);
FClose(infile);
FClose(outtree);
#ifdef MAC
fixmacfile(outtreename);
fixmacfile(outfilename);
#endif
#ifdef WIN32
phyRestoreConsoleAttributes();
#endif
embExit();
return 0;
} /* Mixed parsimony by uphill search */
PHYLIPNEW-3.69.650/src/dolmove.c 0000664 0001750 0001750 00000111353 11616234204 012671 0000000 0000000 #include "phylip.h"
#include "moves.h"
#include "disc.h"
#include "dollo.h"
/* version 3.6. (c) Copyright 1993-2004 by the University of Washington.
Written by Joseph Felsenstein, Akiko Fuseki, Sean Lamont, and Andrew Keeffe.
Permission is granted to copy and use this program provided no fee is
charged for it and provided that this copyright notice is not removed. */
#define overr 4
#define which 1
AjPPhyloState* phylostates = NULL;
AjPPhyloProp phyloanc = NULL;
AjPPhyloProp phylofact = NULL;
AjPPhyloProp phyloweights = NULL;
AjPPhyloTree* phylotrees = NULL;
typedef enum {
horiz, vert, up, overt, upcorner, downcorner, onne, zerro, question, polym
} chartype;
typedef enum { rearr, flipp, reroott, none } rearrtype;
typedef enum {
arb, use, spec
} howtree;
#ifndef OLDC
/* function prototypes */
//void getoptions(void);
void emboss_getoptions(char *pgm, int argc, char *argv[]);
void inputoptions(void);
void allocrest(void);
void doinput(void);
void configure(void);
void prefix(chartype);
void postfix(chartype);
void makechar(chartype);
void dolmove_correct(node *);
void dolmove_count(node *);
void preorder(node *);
void evaluate(node *);
void reroot(node *);
void dolmove_hyptrav(node *);
void dolmove_hypstates(void);
void grwrite(chartype, long, long *);
void dolmove_drawline(long);
void dolmove_printree(void);
void arbitree(void);
void yourtree(void);
void initdolmovenode(node **, node **, node *, long, long, long *,
long *, initops, pointarray, pointarray, Char *, Char *, char**);
void buildtree(void);
void rearrange(void);
void tryadd(node *, node **, node **, double *);
void addpreorder(node *, node *, node *, double *);
void try(void);
void undo(void);
void treewrite(boolean);
void clade(void);
void flip(void);
void changeoutgroup(void);
void redisplay(void);
void treeconstruct(void);
/* function prototypes */
#endif
Char infilename[FNMLNGTH],intreename[FNMLNGTH], ancfilename[FNMLNGTH], factfilename[FNMLNGTH], weightfilename[FNMLNGTH];
const char* outtreename;
AjPFile embossouttree;
node *root;
long outgrno, col, screenlines, screenwidth, scrollinc,treelines,
leftedge,topedge,vmargin,hscroll,vscroll,farthest;
/* outgrno indicates outgroup */
boolean weights, thresh, ancvar, questions, dollo, factors,
waswritten;
boolean *ancone, *anczero, *ancone0, *anczero0;
Char *factor;
pointptr treenode; /* pointers to all nodes in tree */
double threshold;
double *threshwt;
unsigned char cha[10];
boolean reversed[10];
boolean graphic[10];
howtree how;
char *progname;
char ch;
/* Variables for treeread */
boolean usertree, goteof, firsttree, haslengths;
pointarray nodep;
node *grbg;
long *zeros;
/* Local variables for treeconstruct, propagated globally for c version: */
long dispchar, dispword, dispbit, atwhat, what, fromwhere, towhere,
oldoutgrno, compatible;
double like, bestyet, gotlike;
Char *guess;
boolean display, newtree, changed, subtree, written, oldwritten, restoring,
wasleft, oldleft, earlytree;
boolean *in_tree;
steptr numsteps;
long fullset;
bitptr zeroanc, oneanc;
node *nuroot;
rearrtype lastop;
steptr numsone, numszero;
boolean *names;
void emboss_getoptions(char *pgm, int argc, char *argv[])
{
AjPStr method = NULL;
AjPStr initialtree = NULL;
how = arb;
usertree = false;
goteof = false;
thresh = false;
threshold = spp;
weights = false;
ancvar = false;
factors = false;
dollo = true;
screenlines = 24;
scrollinc = 20;
screenwidth = 80;
embInitPV(pgm, argc, argv, "PHYLIPNEW",VERSION);
phylostates = ajAcdGetDiscretestates("infile");
phyloweights = ajAcdGetProperties("weights");
if(phyloweights) weights = true;
phyloanc = ajAcdGetProperties("ancfile");
if(phyloanc) ancvar = true;
initialtree = ajAcdGetListSingle("initialtree");
if(ajStrMatchC(initialtree, "a")) how = arb;
if(ajStrMatchC(initialtree, "u")) how = use;
if(ajStrMatchC(initialtree, "s")) {
how = spec;
phylotrees = ajAcdGetTree("intreefile");
usertree = true;
}
phylofact = ajAcdGetProperties("factorfile");
if(phylofact) factors = true;
method = ajAcdGetListSingle("method");
if(ajStrMatchC(method, "d")) dollo = true;
else dollo = false;
thresh = ajAcdGetToggle("dothreshold");
if(thresh) threshold = ajAcdGetFloat("threshold");
screenwidth = ajAcdGetInt("screenwidth");
screenlines = ajAcdGetInt("screenlines");
if (scrollinc < screenwidth / 2.0)
hscroll = scrollinc;
else
hscroll = screenwidth / 2;
if (scrollinc < screenlines / 2.0)
vscroll = scrollinc;
else
vscroll = screenlines / 2;
printf("\nInteractive Dollo or polymorphism parsimony, version %s\n\n",VERSION);
embossouttree = ajAcdGetOutfile("outtreefile");
emboss_openfile(embossouttree, &outtree, &outtreename);
} /* emboss_getoptions */
void inputoptions()
{
/* input the information on the options */
long i;
for (i = 0; i < (chars); i++)
weight[i] = 1;
if (ancvar)
inputancestorsstr(phyloanc->Str[0],anczero0, ancone0);
if (factors)
inputfactorsstr(phylofact->Str[0], chars, factor, &factors);
if (weights)
inputweightsstr(phyloweights->Str[0], chars, weight, &weights);
putchar('\n');
if (weights)
printweights(stdout, 0, chars, weight, "Characters");
if (factors)
printfactors(stdout, chars, factor, "");
for (i = 0; i < (chars); i++) {
if (!ancvar) {
anczero[i] = true;
ancone[i] = false;
} else {
anczero[i] = anczero0[i];
ancone[i] = ancone0[i];
}
}
if (ancvar)
printancestors(stdout, anczero, ancone);
if (!thresh)
threshold = spp;
questions = false;
for (i = 0; i < (chars); i++) {
questions = (questions || (ancone[i] && anczero[i]));
threshwt[i] = threshold * weight[i];
}
} /* inputoptions */
void allocrest()
{
nayme = (naym *)Malloc(spp*sizeof(naym));
in_tree = (boolean *)Malloc(nonodes*sizeof(boolean));
extras = (steptr)Malloc(chars*sizeof(long));
weight = (steptr)Malloc(chars*sizeof(long));
numszero = (steptr)Malloc(chars*sizeof(long));
numsone = (steptr)Malloc(chars*sizeof(long));
threshwt = (double *)Malloc(chars*sizeof(double));
factor = (Char *)Malloc(chars*sizeof(Char));
ancone = (boolean *)Malloc(chars*sizeof(boolean));
anczero = (boolean *)Malloc(chars*sizeof(boolean));
ancone0 = (boolean *)Malloc(chars*sizeof(boolean));
anczero0 = (boolean *)Malloc(chars*sizeof(boolean));
zeroanc = (bitptr)Malloc(words*sizeof(long));
oneanc = (bitptr)Malloc(words*sizeof(long));
} /* allocrest */
void doinput()
{
/* reads the input data */
inputnumbersstate(phylostates[0], &spp, &chars, &nonodes, 1);
words = chars / bits + 1;
printf("%2ld species, %3ld characters\n", spp, chars);
alloctree(&treenode);
setuptree(treenode);
allocrest();
inputoptions();
disc_inputdata(phylostates[0], treenode, dollo, false, stdout);
} /* doinput */
void configure()
{
/* configure to machine -- set up special characters */
chartype a;
for (a = horiz; (long)a <= (long)polym; a = (chartype)((long)a + 1))
reversed[(long)a] = false;
for (a = horiz; (long)a <= (long)polym; a = (chartype)((long)a + 1))
graphic[(long)a] = false;
if (ibmpc) {
cha[(long)horiz] = 205;
graphic[(long)horiz] = true;
cha[(long)vert] = 186;
graphic[(long)vert] = true;
cha[(long)up] = 186;
graphic[(long)up] = true;
cha[(long)overt] = 205;
graphic[(long)overt] = true;
cha[(long)onne] = 219;
reversed[(long)onne] = true;
cha[(long)zerro] = 176;
graphic[(long)zerro] = true;
cha[(long)question] = 178; /* or try CHR(177) */
cha[(long)polym] = '\001';
reversed[(long)polym] = true;
cha[(long)upcorner] = 200;
graphic[(long)upcorner] = true;
cha[(long)downcorner] = 201;
graphic[(long)downcorner] = true;
graphic[(long)question] = true;
return;
}
if (ansi) {
cha[(long)onne] = ' ';
reversed[(long)onne] = true;
cha[(long)horiz] = cha[(long)onne];
reversed[(long)horiz] = true;
cha[(long)vert] = cha[(long)onne];
reversed[(long)vert] = true;
cha[(long)up] = 'x';
graphic[(long)up] = true;
cha[(long)overt] = 'q';
graphic[(long)overt] = true;
cha[(long)zerro] = 'a';
graphic[(long)zerro] = true;
reversed[(long)zerro] = true;
cha[(long)question] = '?';
cha[(long)question] = '?';
reversed[(long)question] = true;
cha[(long)polym] = '%';
reversed[(long)polym] = true;
cha[(long)upcorner] = 'm';
graphic[(long)upcorner] = true;
cha[(long)downcorner] = 'l';
graphic[(long)downcorner] = true;
return;
}
cha[(long)horiz] = '=';
cha[(long)vert] = ' ';
cha[(long)up] = '!';
cha[(long)overt] = '-';
cha[(long)onne] = '*';
cha[(long)zerro] = '=';
cha[(long)question] = '.';
cha[(long)polym] = '%';
cha[(long)upcorner] = '`';
cha[(long)downcorner] = ',';
} /* configure */
void prefix(chartype a)
{
/* give prefix appropriate for this character */
if (reversed[(long)a])
prereverse(ansi);
if (graphic[(long)a])
pregraph(ansi);
} /* prefix */
void postfix(chartype a)
{
/* give postfix appropriate for this character */
if (reversed[(long)a])
postreverse(ansi);
if (graphic[(long)a])
postgraph(ansi);
} /* postfix */
void makechar(chartype a)
{
/* print out a character with appropriate prefix or postfix */
prefix(a);
putchar(cha[(long)a]);
postfix(a);
} /* makechar */
void dolmove_correct(node *p)
{ /* get final states for intermediate nodes */
long i;
long z0, z1, s0, s1, temp;
if (p->tip)
return;
for (i = 0; i < (words); i++) {
if (p->back == NULL) {
s0 = zeroanc[i];
s1 = oneanc[i];
} else {
s0 = treenode[p->back->index - 1]->statezero[i];
s1 = treenode[p->back->index - 1]->stateone[i];
}
z0 = (s0 & p->statezero[i]) |
(p->next->back->statezero[i] & p->next->next->back->statezero[i]);
z1 = (s1 & p->stateone[i]) |
(p->next->back->stateone[i] & p->next->next->back->stateone[i]);
if (dollo) {
temp = z0 & (~(zeroanc[i] & z1));
z1 &= ~(oneanc[i] & z0);
z0 = temp;
}
temp = fullset & (~z0) & (~z1);
p->statezero[i] = z0 | (temp & s0 & (~s1));
p->stateone[i] = z1 | (temp & s1 & (~s0));
}
} /* dolmove_correct */
void dolmove_count(node *p)
{
/* counts the number of steps in a fork of the tree.
The program spends much of its time in this PROCEDURE */
long i, j, l;
bitptr steps;
steps = (bitptr)Malloc(words*sizeof(long));
if (dollo) {
for (i = 0; i < (words); i++)
steps[i] = (treenode[p->back->index - 1]->stateone[i] &
p->statezero[i] & zeroanc[i]) |
(treenode[p->back->index - 1]->statezero[i] &
p->stateone[i] & oneanc[i]);
} else {
for (i = 0; i < (words); i++)
steps[i] = treenode[p->back->index - 1]->stateone[i] &
treenode[p->back->index - 1]->statezero[i] & p->stateone[i] &
p->statezero[i];
}
j = 1;
l = 0;
for (i = 0; i < (chars); i++) {
l++;
if (l > bits) {
l = 1;
j++;
}
if (((1L << l) & steps[j - 1]) != 0) {
if (((1L << l) & zeroanc[j - 1]) != 0)
numszero[i] += weight[i];
else
numsone[i] += weight[i];
}
}
free(steps);
} /* dolmove_count */
void preorder(node *p)
{
/* go back up tree setting up and counting interior node
states */
if (!p->tip) {
dolmove_correct(p);
preorder(p->next->back);
preorder(p->next->next->back);
}
if (p->back != NULL)
dolmove_count(p);
} /* preorder */
void evaluate(node *r)
{
/* Determines the number of losses or polymorphisms needed for a tree.
This is the minimum number needed to evolve chars on this tree */
long i, stepnum, smaller;
double sum;
boolean nextcompat, thiscompat, done;
sum = 0.0;
for (i = 0; i < (chars); i++) {
numszero[i] = 0;
numsone[i] = 0;
}
for (i = 0; i < (words); i++) {
zeroanc[i] = fullset;
oneanc[i] = 0;
}
compatible = 0;
nextcompat = true;
postorder(r);
preorder(r);
for (i = 0; i < (words); i++) {
zeroanc[i] = 0;
oneanc[i] = fullset;
}
postorder(r);
preorder(r);
for (i = 0; i < (chars); i++) {
smaller = spp * weight[i];
numsteps[i] = smaller;
if (anczero[i]) {
numsteps[i] = numszero[i];
smaller = numszero[i];
}
if (ancone[i] && numsone[i] < smaller)
numsteps[i] = numsone[i];
stepnum = numsteps[i] + extras[i];
if (stepnum <= threshwt[i])
sum += stepnum;
else
sum += threshwt[i];
thiscompat = (stepnum <= weight[i]);
if (factors) {
done = (i + 1 == chars);
if (!done)
done = (factor[i + 1] != factor[i]);
nextcompat = (nextcompat && thiscompat);
if (done) {
if (nextcompat)
compatible += weight[i];
nextcompat = true;
}
} else if (thiscompat)
compatible += weight[i];
guess[i] = '?';
if (!ancone[i] ||
(anczero[i] && numszero[i] < numsone[i]))
guess[i] = '0';
else if (!anczero[i] ||
(ancone[i] && numsone[i] < numszero[i]))
guess[i] = '1';
}
like = -sum;
} /* evaluate */
void reroot(node *outgroup)
{
/* reorients tree, putting outgroup in desired position. */
node *p, *q, *newbottom, *oldbottom;
boolean onleft;
if (outgroup->back->index == root->index)
return;
newbottom = outgroup->back;
p = treenode[newbottom->index - 1]->back;
while (p->index != root->index) {
oldbottom = treenode[p->index - 1];
treenode[p->index - 1] = p;
p = oldbottom->back;
}
onleft = (p == root->next);
if (restoring)
if (!onleft && wasleft){
p = root->next->next;
q = root->next;
} else {
p = root->next;
q = root->next->next;
}
else {
if (onleft)
oldoutgrno = root->next->next->back->index;
else
oldoutgrno = root->next->back->index;
wasleft = onleft;
p = root->next;
q = root->next->next;
}
p->back->back = q->back;
q->back->back = p->back;
p->back = outgroup;
q->back = outgroup->back;
if (restoring) {
if (!onleft && wasleft) {
outgroup->back->back = root->next;
outgroup->back = root->next->next;
} else {
outgroup->back->back = root->next->next;
outgroup->back = root->next;
}
} else {
outgroup->back->back = root->next->next;
outgroup->back = root->next;
}
treenode[newbottom->index - 1] = newbottom;
} /* reroot */
void dolmove_hyptrav(node *r)
{
/* compute states at interior nodes for one character */
if (!r->tip)
dolmove_correct(r);
if (((1L << dispbit) & r->stateone[dispword - 1]) != 0) {
if (((1L << dispbit) & r->statezero[dispword - 1]) != 0) {
if (dollo)
r->state = '?';
else
r->state = 'P';
} else
r->state = '1';
} else {
if (((1L << dispbit) & r->statezero[dispword - 1]) != 0)
r->state = '0';
else
r->state = '?';
}
if (!r->tip) {
dolmove_hyptrav(r->next->back);
dolmove_hyptrav(r->next->next->back);
}
} /* dolmove_hyptrav */
void dolmove_hypstates()
{
/* fill in and describe states at interior nodes */
long i, j, k;
for (i = 0; i < (words); i++) {
zeroanc[i] = 0;
oneanc[i] = 0;
}
for (i = 0; i < (chars); i++) {
j = i / bits + 1;
k = i % bits + 1;
if (guess[i] == '0')
zeroanc[j - 1] = ((long)zeroanc[j - 1]) | (1L << k);
if (guess[i] == '1')
oneanc[j - 1] = ((long)oneanc[j - 1]) | (1L << k);
}
filltrav(root);
dolmove_hyptrav(root);
} /* dolmove_hypstates */
void grwrite(chartype c, long num, long *pos)
{
int i;
prefix(c);
for (i = 1; i <= num; i++) {
if ((*pos) >= leftedge && (*pos) - leftedge + 1 < screenwidth)
putchar(cha[(long)c]);
(*pos)++;
}
postfix(c);
} /* grwrite */
void dolmove_drawline(long i)
{
/* draws one row of the tree diagram by moving up tree */
node *p, *q, *r, *first =NULL, *last =NULL;
long n, j, pos;
boolean extra, done;
Char s, cc;
chartype c, d;
pos = 1;
p = nuroot;
q = nuroot;
extra = false;
if (i == (long)p->ycoord && (p == root || subtree)) {
c = overt;
if (display) {
if (p == root)
{
if(!dispchar)
cc = guess[0];
else
cc = guess[dispchar - 1];
}
else
cc = p->state;
switch (cc) {
case '1':
c = onne;
break;
case '0':
c = zerro;
break;
case '?':
c = question;
break;
case 'P':
c = polym;
break;
}
}
if ((subtree))
stwrite("Subtree:", 8, &pos, leftedge, screenwidth);
if (p->index >= 100)
nnwrite(p->index, 3, &pos, leftedge, screenwidth);
else if (p->index >= 10) {
grwrite(c, 1, &pos);
nnwrite(p->index, 2, &pos, leftedge, screenwidth);
} else {
grwrite(c, 2, &pos);
nnwrite(p->index, 1, &pos, leftedge, screenwidth);
}
extra = true;
} else {
if (subtree)
stwrite(" ", 10, &pos, leftedge, screenwidth);
else
stwrite(" ", 2, &pos, leftedge, screenwidth);
}
do {
if (!p->tip) {
r = p->next;
done = false;
do {
if (i >= r->back->ymin && i <= r->back->ymax) {
q = r->back;
done = true;
}
r = r->next;
} while (!(done || r == p));
first = p->next->back;
r = p->next;
while (r->next != p)
r = r->next;
last = r->back;
}
done = (p == q);
n = (long)p->xcoord - (long)q->xcoord;
if (n < 3 && !q->tip)
n = 3;
if (extra) {
n--;
extra = false;
}
if ((long)q->ycoord == i && !done) {
if ((long)q->ycoord > (long)p->ycoord)
d = upcorner;
else
d = downcorner;
c = overt;
s = q->state;
if (s == 'P' && p->state != 'P')
s = p->state;
if (display) {
switch (s) {
case '1':
c = onne;
break;
case '0':
c = zerro;
break;
case '?':
c = question;
break;
case 'P':
c = polym;
break;
}
d = c;
}
if (n > 1) {
grwrite(d, 1, &pos);
grwrite(c, n - 3, &pos);
}
if (q->index >= 100)
nnwrite(q->index, 3, &pos, leftedge, screenwidth);
else if (q->index >= 10) {
grwrite(c, 1, &pos);
nnwrite(q->index, 2, &pos, leftedge, screenwidth);
} else {
grwrite(c, 2, &pos);
nnwrite(q->index, 1, &pos, leftedge, screenwidth);
}
extra = true;
} else if (!q->tip) {
if ((long)last->ycoord > i && (long)first->ycoord < i
&& i != (long)p->ycoord) {
c = up;
if (i < (long)p->ycoord)
s = p->next->back->state;
else
s = p->next->next->back->state;
if (s == 'P' && p->state != 'P')
s = p->state;
if (display) {
switch (s) {
case '1':
c = onne;
break;
case '0':
c = zerro;
break;
case '?':
c = question;
break;
case 'P':
c = polym;
break;
}
}
grwrite(c, 1, &pos);
chwrite(' ', n - 1, &pos, leftedge, screenwidth);
} else
chwrite(' ', n, &pos, leftedge, screenwidth);
} else
chwrite(' ', n, &pos, leftedge, screenwidth);
if (p != q)
p = q;
} while (!done);
if ((long)p->ycoord == i && p->tip) {
n = 0;
for (j = 1; j <= nmlngth; j++) {
if (nayme[p->index - 1][j - 1] != '\0')
n = j;
}
chwrite(':', 1, &pos, leftedge, screenwidth);
for (j = 0; j < n; j++)
chwrite(nayme[p->index - 1][j], 1, &pos, leftedge, screenwidth);
}
putchar('\n');
} /* dolmove_drawline */
void dolmove_printree()
{
/* prints out diagram of the tree */
long tipy;
long i, dow;
if (!subtree)
nuroot = root;
if (changed || newtree)
evaluate(root);
if (display)
dolmove_hypstates();
#ifdef WIN32
if(ibmpc || ansi){
phyClearScreen();
} else {
printf("\n");
}
#else
if (ansi || ibmpc)
printf("\033[2J\033[H");
else
putchar('\n');
#endif
tipy = 1;
dow = down;
if (spp * dow > screenlines && !subtree)
dow--;
printf("(unrooted)");
if (display) {
printf(" ");
makechar(onne);
printf(":1 ");
makechar(question);
printf(":? ");
makechar(zerro);
printf(":0 ");
makechar(polym);
printf(":0/1");
} else
printf(" ");
if (!earlytree) {
printf("%10.1f Steps", -like);
}
if (display)
printf(" SITE%4ld", dispchar);
else
printf(" ");
if (!earlytree) {
printf(" %3ld chars compatible\n", compatible);
}
printf("%-20s",dollo ? "Dollo" : "Polymorphism");
if (changed && !earlytree) {
if (-like < bestyet) {
printf(" BEST YET!");
bestyet = -like;
} else if (fabs(-like - bestyet) < 0.000001)
printf(" (as good as best)");
else {
if (-like < gotlike)
printf(" better");
else if (-like > gotlike)
printf(" worse!");
}
}
printf("\n");
farthest = 0;
coordinates(nuroot, &tipy, 1.5, &farthest);
vmargin = 5;
treelines = tipy - dow;
if (topedge != 1){
printf("** %ld lines above screen **\n", topedge - 1);
vmargin++;}
if ((treelines - topedge + 1) > (screenlines - vmargin))
vmargin++;
for (i = 1; i <= treelines; i++) {
if (i >= topedge && i < topedge + screenlines - vmargin)
dolmove_drawline(i);
}
if ((treelines - topedge + 1) > (screenlines - vmargin))
printf("** %ld lines below screen **\n",
treelines - (topedge - 1 + screenlines - vmargin));
if (treelines - topedge + vmargin + 1 < screenlines)
putchar('\n');
gotlike = -like;
changed = false;
} /* dolmove_printree */
void arbitree()
{
long i;
root = treenode[0];
add2(treenode[0], treenode[1], treenode[spp], &root, restoring, wasleft,
treenode);
for (i = 3; i <= (spp); i++)
add2(treenode[spp + i - 3], treenode[i - 1], treenode[spp + i - 2], &root,
restoring, wasleft, treenode);
for (i = 0; i < (nonodes); i++)
in_tree[i] = true;
} /* arbitree */
void yourtree()
{
long i, j;
boolean ok;
root = treenode[0];
add2(treenode[0], treenode[1], treenode[spp], &root, restoring, wasleft,
treenode);
i = 2;
do {
i++;
dolmove_printree();
printf("Add species%3ld: ", i);
for (j = 0; j < nmlngth; j++)
putchar(nayme[i - 1][j]);
do {
printf("\nbefore node (type number): ");
inpnum(&j, &ok);
ok = (ok && ((j >= 1 && j < i) || (j > spp && j < spp + i - 1)));
if (!ok)
printf("Impossible number. Please try again:\n");
} while (!ok);
add2(treenode[j - 1], treenode[i - 1], treenode[spp + i - 2], &root,
restoring, wasleft, treenode);
} while (i != spp);
for (i = 0; i < (nonodes); i++)
in_tree[i] = true;
} /* yourtree */
void initdolmovenode(node **p, node **grbg, node *q, long len, long nodei,
long *ntips, long *parens, initops whichinit,
pointarray treenode, pointarray nodep, Char *str, Char *ch,
char **treestr)
{
/* initializes a node */
/* LM 7/27 I added this function and the commented lines around */
/* treeread() to get the program running, but all 4 move programs*/
/* are improperly integrated into the v4.0 support files. As is */
/* this is a patchwork function */
boolean minusread;
double valyew, divisor;
switch (whichinit) {
case bottom:
gnutreenode(grbg, p, nodei, chars, zeros);
treenode[nodei - 1] = *p;
break;
case nonbottom:
gnutreenode(grbg, p, nodei, chars, zeros);
break;
case tip:
match_names_to_data (str, treenode, p, spp);
break;
case length:
processlength(&valyew, &divisor, ch, &minusread, treestr, parens);
/* process lengths and discard */
default: /*cases hslength,hsnolength,treewt,unittrwt,iter,*/
break; /*length should never occur */
}
} /* initdolmovenode */
void buildtree()
{
long i, j, nextnode;
node *p;
char* treestr;
changed = false;
newtree = false;
switch (how) {
case arb:
arbitree();
break;
case use:
names = (boolean *)Malloc(spp*sizeof(boolean));
firsttree = true; /**/
nodep = NULL; /**/
nextnode = 0; /**/
haslengths = 0; /**/
zeros = (long *)Malloc(chars*sizeof(long)); /**/
for (i = 0; i < chars; i++) /**/
zeros[i] = 0; /**/
treestr = ajStrGetuniquePtr(&phylotrees[0]->Tree);
treeread(&treestr, &root, treenode, &goteof, &firsttree,
nodep, &nextnode, &haslengths,
&grbg, initdolmovenode,false,nonodes);
for (i = spp; i < (nonodes); i++) {
p = treenode[i];
for (j = 1; j <= 3; j++) {
p->stateone = (bitptr)Malloc(words*sizeof(long));
p->statezero = (bitptr)Malloc(words*sizeof(long));
p = p->next;
}
} /* debug: see comment at initdolmovenode() */
/*treeread(which, ch, &root, treenode, names);*/
for (i = 0; i < (spp); i++)
in_tree[i] = names[i];
free(names);
FClose(intree);
break;
case spec:
yourtree();
break;
}
outgrno = root->next->back->index;
if (in_tree[outgrno - 1])
reroot(treenode[outgrno - 1]);
} /* buildtree */
void rearrange()
{
long i, j;
boolean ok1, ok2;
node *p, *q;
printf("Remove everything to the right of which node? ");
inpnum(&i, &ok1);
ok1 = (ok1 && i >= 1 && i < spp * 2 && i != root->index);
if (ok1) {
printf("Add before which node? ");
inpnum(&j, &ok2);
ok2 = (ok2 && j >= 1 && j < spp * 2);
if (ok2) {
ok2 = (treenode[j - 1] != treenode[treenode[i - 1]->back->index - 1]);
p = treenode[j - 1];
while (p != root) {
ok2 = (ok2 && p != treenode[i - 1]);
p = treenode[p->back->index - 1];
}
if (ok1 && ok2) {
what = i;
q = treenode[treenode[i - 1]->back->index - 1];
if (q->next->back->index == i)
fromwhere = q->next->next->back->index;
else
fromwhere = q->next->back->index;
towhere = j;
re_move2(&treenode[i - 1], &q, &root, &wasleft, treenode);
add2(treenode[j - 1], treenode[i - 1], q, &root, restoring, wasleft, treenode);
}
lastop = rearr;
}
}
changed = (ok1 && ok2);
dolmove_printree();
if (!(ok1 && ok2))
printf("Not a possible rearrangement. Try again: \n");
else {
oldwritten = written;
written = false;
}
} /* rearrange */
void tryadd(node *p, node **item, node **nufork, double *place)
{
/* temporarily adds one fork and one tip to the tree.
Records scores in ARRAY place */
add2(p, *item, *nufork, &root, restoring, wasleft, treenode);
evaluate(root);
place[p->index - 1] = -like;
re_move2(item, nufork, &root, &wasleft, treenode);
} /* tryadd */
void addpreorder(node *p, node *item_, node *nufork_, double *place)
{
/* traverses a binary tree, calling PROCEDURE tryadd
at a node before calling tryadd at its descendants */
node *item, *nufork;
item = item_;
nufork = nufork_;
if (p == NULL)
return;
tryadd(p, &item,&nufork,place);
if (!p->tip) {
addpreorder(p->next->back, item,nufork,place);
addpreorder(p->next->next->back,item,nufork,place);
}
} /* addpreorder */
void try()
{
/* Remove node, try it in all possible places */
double *place;
long i, j, oldcompat;
double current;
node *q, *dummy, *rute;
boolean tied, better, ok;
printf("Try other positions for which node? ");
inpnum(&i, &ok);
if (!(ok && i >= 1 && i <= nonodes && i != root->index)) {
printf("Not a possible choice! ");
return;
}
printf("WAIT ...\n");
place = (double *)Malloc(nonodes*sizeof(double));
for (j = 0; j < (nonodes); j++)
place[j] = -1.0;
evaluate(root);
current = -like;
oldcompat = compatible;
what = i;
q = treenode[treenode[i - 1]->back->index - 1];
if (q->next->back->index == i)
fromwhere = q->next->next->back->index;
else
fromwhere = q->next->back->index;
rute = root;
if (root->index == treenode[i - 1]->back->index) {
if (treenode[treenode[i - 1]->back->index - 1]->next->back == treenode[i - 1])
rute = treenode[treenode[i - 1]->back->index - 1]->next->next->back;
else
rute = treenode[treenode[i - 1]->back->index - 1]->next->back;
}
re_move2(&treenode[i - 1], &dummy, &root, &wasleft, treenode);
oldleft = wasleft;
root = rute;
addpreorder(root, treenode[i - 1], dummy, place);
wasleft = oldleft;
restoring = true;
add2(treenode[fromwhere - 1], treenode[what - 1], dummy, &root,
restoring, wasleft, treenode);
like = -current;
compatible = oldcompat;
restoring = false;
better = false;
printf(" BETTER: ");
for (j = 1; j <= (nonodes); j++) {
if (place[j - 1] < current && place[j - 1] >= 0.0) {
printf("%3ld:%6.2f", j, place[j - 1]);
better = true;
}
}
if (!better)
printf(" NONE");
printf("\n TIED: ");
tied = false;
for (j = 1; j <= (nonodes); j++) {
if (fabs(place[j - 1] - current) < 1.0e-6 && j != fromwhere) {
if (j < 10)
printf("%2ld", j);
else
printf("%3ld", j);
tied = true;
}
}
if (tied)
printf(":%6.2f\n", current);
else
printf("NONE\n");
changed = true;
free(place);
} /* try */
void undo()
{
/* restore to tree before last rearrangement */
long temp;
boolean btemp;
node *q;
switch (lastop) {
case rearr:
restoring = true;
oldleft = wasleft;
re_move2(&treenode[what - 1], &q, &root, &wasleft, treenode);
btemp = wasleft;
wasleft = oldleft;
add2(treenode[fromwhere - 1], treenode[what - 1], q, &root,
restoring, wasleft, treenode);
wasleft = btemp;
restoring = false;
temp = fromwhere;
fromwhere = towhere;
towhere = temp;
changed = true;
break;
case flipp:
q = treenode[atwhat - 1]->next->back;
treenode[atwhat - 1]->next->back =
treenode[atwhat - 1]->next->next->back;
treenode[atwhat - 1]->next->next->back = q;
treenode[atwhat - 1]->next->back->back = treenode[atwhat - 1]->next;
treenode[atwhat - 1]->next->next->back->back =
treenode[atwhat - 1]->next->next;
break;
case reroott:
restoring = true;
temp = oldoutgrno;
oldoutgrno = outgrno;
outgrno = temp;
reroot(treenode[outgrno - 1]);
restoring = false;
break;
case none:
/* blank case */
break;
}
dolmove_printree();
if (lastop == none) {
printf("No operation to undo! ");
return;
}
btemp = oldwritten;
oldwritten = written;
written = btemp;
} /* undo */
void treewrite(boolean done)
{
/* write out tree to a file */
if (!done)
dolmove_printree();
if (waswritten && ch == 'N')
return;
col = 0;
treeout(root, 1, &col, root);
printf("\nTree written to file \"%s\"\n\n", outtreename);
waswritten = true;
written = true;
FClose(outtree);
#ifdef MAC
fixmacfile(outtreename);
#endif
} /* treewrite */
void clade()
{
/* pick a subtree and show only that on screen */
long i;
boolean ok;
printf("Select subtree rooted at which node (0 for whole tree)? ");
inpnum(&i, &ok);
ok = (ok && ((unsigned)i) <= ((unsigned)nonodes));
if (ok) {
subtree = (i > 0);
if (subtree)
nuroot = treenode[i - 1];
else
nuroot = root;
}
dolmove_printree();
if (!ok)
printf("Not possible to use this node. ");
} /* clade */
void flip()
{
/* flip at a node left-right */
long i;
boolean ok;
node *p;
printf("Flip branches at which node? ");
inpnum(&i, &ok);
ok = (ok && i > spp && i <= nonodes);
if (ok) {
p = treenode[i - 1]->next->back;
treenode[i - 1]->next->back = treenode[i - 1]->next->next->back;
treenode[i - 1]->next->next->back = p;
treenode[i - 1]->next->back->back = treenode[i - 1]->next;
treenode[i - 1]->next->next->back->back = treenode[i - 1]->next->next;
atwhat = i;
lastop = flipp;
}
dolmove_printree();
if (ok) {
oldwritten = written;
written = false;
return;
}
if (i >= 1 && i <= spp)
printf("Can't flip there. ");
else
printf("No such node. ");
} /* flip */
void changeoutgroup()
{
long i;
boolean ok;
oldoutgrno = outgrno;
do {
printf("Which node should be the new outgroup? ");
inpnum(&i, &ok);
ok = (ok && in_tree[i - 1] && i >= 1 && i <= nonodes &&
i != root->index);
if (ok)
outgrno = i;
} while (!ok);
if (in_tree[outgrno - 1])
reroot(treenode[outgrno - 1]);
changed = true;
lastop = reroott;
dolmove_printree();
oldwritten = written;
written = false;
} /* changeoutgroup */
void redisplay()
{
boolean done;
char input[100];
done = false;
waswritten = false;
do {
fprintf(stderr, "NEXT? (R # + - S . T U W O F H J K L C ? X Q) ");
fprintf(stderr, "(? for Help): ");
#ifdef WIN32
phyFillScreenColor();
#endif
getstryng(input);
ch = input[0];
uppercase(&ch);
if (strchr("RSWH#.O?+TFX-UCQHJKL",ch) != NULL){
switch (ch) {
case 'R':
rearrange();
break;
case '#':
nextinc(&dispchar, &dispword, &dispbit, chars, bits, &display,
numsteps, weight);
dolmove_printree();
break;
case '+':
nextchar(&dispchar, &dispword, &dispbit, chars, bits, &display);
dolmove_printree();
break;
case '-':
prevchar(&dispchar, &dispword, &dispbit, chars, bits, &display);
dolmove_printree();
break;
case 'S':
show(&dispchar, &dispword, &dispbit, chars, bits, &display);
dolmove_printree();
break;
case '.':
dolmove_printree();
break;
case 'T':
try();
break;
case 'U':
undo();
break;
case 'W':
treewrite(done);
break;
case 'O':
changeoutgroup();
break;
case 'F':
flip();
break;
case 'H':
window(left, &leftedge, &topedge, hscroll, vscroll, treelines,
screenlines, screenwidth, farthest, subtree);
dolmove_printree();
break;
case 'J':
window(downn, &leftedge, &topedge, hscroll, vscroll, treelines,
screenlines, screenwidth, farthest, subtree);
dolmove_printree();
break;
case 'K':
window(upp, &leftedge, &topedge, hscroll, vscroll, treelines,
screenlines, screenwidth, farthest, subtree);
dolmove_printree();
break;
case 'L':
window(right, &leftedge, &topedge, hscroll, vscroll, treelines,
screenlines, screenwidth, farthest, subtree);
dolmove_printree();
break;
case 'C':
clade();
break;
case '?':
help("character");
dolmove_printree();
break;
case 'X':
done = true;
break;
case 'Q':
done = true;
break;
}
}
} while (!done);
if (!written) {
do {
fprintf(stderr,"Do you want to write out the tree to a file? (Y or N): ");
#ifdef WIN32
phyFillScreenColor();
#endif
getstryng(input);
ch = input[0];
} while (ch != 'Y' && ch != 'y' && ch != 'N' && ch != 'n');
}
if (ch == 'Y' || ch == 'y')
treewrite(done);
} /* redisplay */
void treeconstruct()
{
/* constructs a binary tree from the pointers in treenode. */
restoring = false;
subtree = false;
display = false;
dispchar = 0;
fullset = (1L << (bits + 1)) - (1L << 1);
guess = (Char *)Malloc(chars*sizeof(Char));
numsteps = (steptr)Malloc(chars*sizeof(long));
earlytree = true;
buildtree();
waswritten = false;
printf("\nComputing steps needed for compatibility in sites ...\n\n");
newtree = true;
earlytree = false;
dolmove_printree();
bestyet = -like;
gotlike = -like;
lastop = none;
newtree = false;
written = false;
lastop = none;
redisplay();
} /* treeconstruct */
int main(int argc, Char *argv[])
{ /* Interactive Dollo/polymorphism parsimony */
/* reads in spp, chars, and the data. Then calls treeconstruct to
construct the tree and query the user */
#ifdef MAC
argc = 1; /* macsetup("Dolmove",""); */
argv[0] = "Dolmove";
#endif
init(argc, argv);
emboss_getoptions("fdolmove",argc,argv);
progname = argv[0];
topedge = 1;
leftedge = 1;
ibmpc = IBMCRT;
ansi = ANSICRT;
root = NULL;
bits = 8*sizeof(long) - 1;
doinput();
configure();
treeconstruct();
if (waswritten) {
FClose(outtree);
#ifdef MAC
fixmacfile(outtreename);
#endif
}
FClose(infile);
#ifdef WIN32
phyRestoreConsoleAttributes();
#endif
embExit();
return 0;
} /* Interactive Dollo/polymorphism parsimony */
PHYLIPNEW-3.69.650/src/dnamlk.c 0000664 0001750 0001750 00000164345 11616234204 012503 0000000 0000000 /* version 3.6. (c) Copyright 1986-2007 by the University of Washington
and by Joseph Felsenstein. Written by Joseph Felsenstein. Permission is
granted to copy and use this program provided no fee is charged for it
and provided that this copyright notice is not removed. */
#include
#include
#include "phylip.h"
#include "seq.h"
#include "mlclock.h"
#include "printree.h"
#define over 60 /* Maximum xcoord of tip nodes */
/* These are redefined from phylip.h */
/* Fractional accuracy to which node tymes are optimized */
#undef epsilon
double epsilon = 1e-3;
/* Number of (failed) passes over the tree before giving up */
#undef smoothings
#define smoothings 4
#undef initialv
#define initialv 0.3
typedef struct valrec {
double rat, ratxi, ratxv, orig_zz, z1, y1, z1zz, z1yy, xiz1,
xiy1xv;
double *ww, *zz, *wwzz, *vvzz;
} valrec;
struct options {
boolean auto_;
boolean ctgry;
long categs;
long rcategs;
boolean freqsfrom;
boolean gama;
boolean invar;
boolean global;
boolean hypstate;
boolean jumble;
long njumble;
double lambda;
double lambda1;
boolean lengthsopt;
boolean trout;
double ttratio;
boolean ttr;
boolean usertree;
boolean weights;
boolean printdata;
boolean dotdiff;
boolean progress;
boolean treeprint;
boolean interleaved;
};
typedef double contribarr[maxcategs];
valrec ***tbl;
AjPSeqset* seqsets = NULL;
AjPPhyloProp phyloratecat = NULL;
AjPPhyloProp phyloweights = NULL;
AjPPhyloTree* phylotrees;
ajint numseqs;
ajint numwts;
#ifndef OLDC
/* function prototypes */
//void getoptions(void);
static void emboss_getoptions(char *pgm, int argc, char *argv[]);
static void initmemrates(void);
static void allocrest(void);
static void doinit(void);
static void inputoptions(void);
static void makeweights(void);
static void getinput(void);
static void inittable_for_usertree (char *);
static void inittable(void);
static void alloc_nvd(long, nuview_data *);
static void free_nvd(nuview_data *);
static boolean nuview(node *);
static double dnamlk_evaluate(node *);
static boolean update(node *);
static boolean smooth(node *);
static void restoradd(node *, node *, node *, double);
static void dnamlk_add(node *, node *, node *);
static void dnamlk_re_move(node **, node **, boolean);
static void tryadd(node *, node **, node **);
static void addpreorder(node *, node *, node *, boolean, boolean);
static boolean tryrearr(node *);
static boolean repreorder(node *);
static void rearrange(node **);
static void initdnamlnode(node **, node **, node *, long, long,
long *, long *, initops, pointarray, pointarray,
Char *, Char *, char **);
static boolean tymetrav(node *);
static void reconstr(node *, long);
static void rectrav(node *, long, long);
static void summarize(FILE *fp);
static void dnamlk_treeout(node *);
static void init_tymes(node *p, double minlength);
static void treevaluate(void);
static void maketree(void);
static void reallocsites(void);
/* function prototypes */
#endif
Char infilename[FNMLNGTH], intreename[FNMLNGTH], catfilename[FNMLNGTH], weightfilename[FNMLNGTH];
const char* outfilename;
const char* outtreename;
AjPFile embossoutfile;
AjPFile embossouttree;
double *rrate;
long sites, weightsum, categs, datasets, ith, njumble, jumb, numtrees, shimotrees;
/* sites = number of sites in actual sequences
numtrees = number of user-defined trees */
long inseed, inseed0, mx, mx0, mx1;
boolean freqsfrom, global, global2=0, jumble, trout, usertree, weights,
rctgry, ctgry, ttr, auto_, progress, mulsets, firstset, hypstate,
smoothit, polishing, justwts, gama, invar;
boolean lengthsopt = false; /* Use lengths in user tree option */
boolean lngths = false; /* Actually use lengths (depends on
each input tree) */
tree curtree, bestree, bestree2;
node *qwhere, *grbg;
double *tymes;
double xi, xv, ttratio, ttratio0, freqa, freqc, freqg, freqt, freqr,
freqy, freqar, freqcy, freqgr, freqty, fracchange, sumrates,
cv, alpha, lambda, lambda1, invarfrac;
long *enterorder;
steptr aliasweight;
double *rate;
longer seed;
double *probcat;
long iprobcat;
contribarr *contribution;
char *progname;
long rcategs;
long **mp;
char basechar[16] = "acmgrsvtwyhkdbn";
/* Local variables for maketree, propagated globally for C version: */
long k, maxwhich, col;
double like, bestyet, maxlogl;
boolean lastsp;
boolean smoothed; /* set true before each smoothing run, and set false
each time a branch cannot be completely optimized. */
double *l0gl;
double expon1i[maxcategs], expon1v[maxcategs],
expon2i[maxcategs], expon2v[maxcategs];
node *there;
double **l0gf;
Char ch, ch2;
void emboss_getoptions(char *pgm, int argc, char *argv[])
{
AjPStr gammamethod = NULL;
ajint i;
AjPFloat basefreq;
AjPFloat hmmrates;
AjPFloat hmmprob;
AjPFloat arrayval;
double probsum=0.0;
auto_ = false;
ctgry = false;
rctgry = false;
categs = 1;
rcategs = 1;
freqsfrom = true;
gama = false;
invar = false;
global = false;
hypstate = false;
jumble = false;
njumble = 1;
lambda = 1.0;
lambda1 = 0.0;
lngths = false;
trout = true;
ttratio = 2.0;
ttr = false;
usertree = false;
weights = false;
printdata = false;
progress = true;
treeprint = true;
interleaved = true;
datasets = 1;
mulsets = false;
embInitPV(pgm, argc, argv, "PHYLIPNEW",VERSION);
seqsets = ajAcdGetSeqsetall("sequence");
numseqs = 0;
while (seqsets[numseqs])
numseqs++;
phylotrees = ajAcdGetTree("intreefile");
if (phylotrees)
{
numtrees = 0;
while (phylotrees[numtrees])
numtrees++;
usertree = true;
lngths = ajAcdGetBoolean("lengths");
}
numwts = 0;
phyloweights = ajAcdGetProperties("weights");
if (phyloweights)
{
weights = true;
numwts = ajPhyloPropGetSize(phyloweights);
}
if (numseqs > 1) {
mulsets = true;
datasets = numseqs;
}
else if (numwts > 1) {
mulsets = true;
datasets = numwts;
justwts = true;
}
categs = ajAcdGetInt("ncategories");
if (categs > 1) {
ctgry = true;
rate = (double *) Malloc(categs * sizeof(double));
arrayval = ajAcdGetArray("rate");
emboss_initcategs(arrayval, categs, rate);
}
else{
rate = (double *) Malloc(categs*sizeof(double));
rate[0] = 1.0;
}
phyloratecat = ajAcdGetProperties("categories");
gammamethod = ajAcdGetListSingle("gammatype");
if(ajStrMatchC(gammamethod, "n")) {
rrate = (double *) Malloc(rcategs*sizeof(double));
probcat = (double *) Malloc(rcategs*sizeof(double));
iprobcat = rcategs;
rrate[0] = 1.0;
probcat[0] = 1.0;
}
else {
rctgry = true;
auto_ = ajAcdGetBoolean("adjsite");
if(auto_) {
lambda = ajAcdGetFloat("lambda");
lambda = 1 / lambda;
lambda1 = 1.0 - lambda;
}
}
if(ajStrMatchC(gammamethod, "g")) {
gama = true;
rcategs = ajAcdGetInt("ngammacat");
cv = ajAcdGetFloat("gammacoefficient");
alpha = 1.0 / (cv*cv);
initmemrates();
initgammacat(rcategs, alpha, rrate, probcat);
}
else if(ajStrMatchC(gammamethod, "i")) {
invar = true;
rcategs = ajAcdGetInt("ninvarcat");
cv = ajAcdGetFloat("invarcoefficient");
alpha = 1.0 / (cv*cv);
invarfrac = ajAcdGetFloat("invarfrac");
initmemrates();
initgammacat(rcategs-1, alpha, rrate, probcat);
for (i=0; i < rcategs-1 ; i++)
probcat[i] = probcat[i]*(1.0-invarfrac);
probcat[rcategs-1] = invarfrac;
rrate[rcategs-1] = 0.0;
}
else if(ajStrMatchC(gammamethod, "h")) {
rcategs = ajAcdGetInt("nhmmcategories");
initmemrates();
hmmrates = ajAcdGetArray("hmmrates");
emboss_initcategs(hmmrates, rcategs,rrate);
hmmprob = ajAcdGetArray("hmmprobabilities");
for (i=0; i < rcategs; i++){
probcat[i] = ajFloatGet(hmmprob, i);
probsum += probcat[i];
}
}
ttratio = ajAcdGetFloat("ttratio");
if(!usertree) {
global = ajAcdGetBoolean("global");
njumble = ajAcdGetInt("njumble");
if(njumble >0) {
inseed = ajAcdGetInt("seed");
jumble = true;
emboss_initseed(inseed, &inseed0, seed);
}
else njumble = 1;
}
if((mulsets) && (!jumble)) {
jumble = true;
inseed = ajAcdGetInt("seed");
emboss_initseed(inseed, &inseed0, seed);
}
printdata = ajAcdGetBoolean("printdata");
progress = ajAcdGetBoolean("progress");
treeprint = ajAcdGetBoolean("treeprint");
trout = ajAcdGetToggle("trout");
hypstate = ajAcdGetBoolean("hypstate");
freqsfrom = ajAcdGetToggle("freqsfrom");
if(!freqsfrom) {
basefreq = ajAcdGetArray("basefreq");
freqa = ajFloatGet(basefreq, 0);
freqc = ajFloatGet(basefreq, 1);
freqg = ajFloatGet(basefreq, 2);
freqt = ajFloatGet(basefreq, 3);
}
embossoutfile = ajAcdGetOutfile("outfile");
emboss_openfile(embossoutfile, &outfile, &outfilename);
if(trout) {
embossouttree = ajAcdGetOutfile("outtreefile");
emboss_openfile(embossouttree, &outtree, &outtreename);
}
fprintf(outfile, "\nNucleic acid sequence Maximum Likelihood");
fprintf(outfile, " method, version %s\n\n",VERSION);
/*
printf("\n mulsets: %s",(mulsets ? "true" : "false"));
printf("\n datasets : %ld",(datasets));
printf("\n rctgry : %s",(rctgry ? "true" : "false"));
printf("\n gama : %s",(gama ? "true" : "false"));
printf("\n invar : %s",(invar ? "true" : "false"));
printf("\n\n ctgry: %s",(ctgry ? "true" : "false"));
printf("\n categs : %ld",(categs));
printf("\n rcategs : %ld",(rcategs));
printf("\n auto_: %s",(auto_ ? "true" : "false"));
printf("\n freqsfrom : %s",(freqsfrom ? "true" : "false"));
printf("\n global : %s",(global ? "true" : "false"));
printf("\n hypstate : %s",(hypstate ? "true" : "false"));
printf("\n invar : %s",(invar ? "true" : "false"));
printf("\n jumble : %s",(jumble ? "true" : "false"));
printf("\n njumble : %ld",(njumble));
printf("\n lngths : %s",(lngths ? "true" : "false"));
printf("\n lambda : %f",(lambda));
printf("\n lambda1 : %f",(lambda1));
printf("\n cv : %f",(cv));
printf("\n freqa : %f",(freqa));
printf("\n freqc : %f",(freqc));
printf("\n freqg : %f",(freqg));
printf("\n freqt : %f",(freqt));
printf("\n trout : %s",(trout ? "true" : "false"));
printf("\n ttratio : %f",(ttratio));
printf("\n probsum : %f",(probsum));
printf("\n ttr : %s",(ttr ? "true" : "false"));
printf("\n usertree : %s",(usertree ? "true" : "false"));
printf("\n weights: %s",(weights ? "true" : "false"));
printf("\n printdata : %s",(printdata ? "true" : "false"));
printf("\n progress : %s",(progress ? "true" : "false"));
printf("\n treeprint: %s",(treeprint ? "true" : "false"));
printf("\n interleaved : %s \n\n",(interleaved ? "true" : "false"));
for (i=0;iStr[ith-1], sites, weight, &weights);
weightsum = 0;
for (i = 0; i < sites; i++)
weightsum += weight[i];
if (ctgry && categs > 1) {
inputcategsstr(phyloratecat->Str[0], 0, sites, category, categs, "DnaMLK");
if (printdata)
printcategs(outfile, sites, category, "Site categories");
}
if (weights && printdata)
printweights(outfile, 0, sites, weight, "Sites");
} /* inputoptions */
static void makeweights(void)
{
/* make up weights vector to avoid duplicate computations */
long i;
for (i = 1; i <= sites; i++) {
alias[i - 1] = i;
ally[i - 1] = 0;
aliasweight[i - 1] = weight[i - 1];
location[i - 1] = 0;
}
sitesort2(sites, aliasweight);
sitecombine2(sites, aliasweight);
sitescrunch2(sites, 1, 2, aliasweight);
for (i = 1; i <= sites; i++) {
if (aliasweight[i - 1] > 0)
endsite = i;
}
for (i = 1; i <= endsite; i++) {
ally[alias[i - 1] - 1] = alias[i - 1];
location[alias[i - 1] - 1] = i;
}
contribution = (contribarr *) Malloc( endsite*sizeof(contribarr));
} /* makeweights */
static void getinput(void)
{
/* reads the input data */
inputoptions();
if (!freqsfrom)
getbasefreqs(freqa, freqc, freqg, freqt, &freqr, &freqy, &freqar, &freqcy,
&freqgr, &freqty, &ttratio, &xi, &xv, &fracchange,
freqsfrom, true);
if (!justwts || firstset)
seq_inputdata(seqsets[ith-1], sites);
makeweights();
setuptree2(&curtree);
if (!usertree) {
setuptree2(&bestree);
if (njumble > 1)
setuptree2(&bestree2);
}
allocx(nonodes, rcategs, curtree.nodep, usertree);
if (!usertree) {
allocx(nonodes, rcategs, bestree.nodep, 0);
if (njumble > 1)
allocx(nonodes, rcategs, bestree2.nodep, 0);
}
makevalues2(rcategs, curtree.nodep, endsite, spp, y, alias);
if (freqsfrom) {
empiricalfreqs(&freqa, &freqc, &freqg, &freqt, aliasweight, curtree.nodep);
getbasefreqs(freqa, freqc, freqg, freqt, &freqr, &freqy, &freqar, &freqcy,
&freqgr, &freqty, &ttratio, &xi, &xv, &fracchange,
freqsfrom, true);
}
if (!justwts || firstset)
fprintf(outfile, "\nTransition/transversion ratio = %10.6f\n\n", ttratio);
} /* getinput */
static void inittable_for_usertree (char* treestr)
{
/* If there's a user tree, then the ww/zz/wwzz/vvzz elements need
to be allocated appropriately. */
long num_comma;
long i, j;
/* First, figure out the largest possible furcation, i.e. the number
of commas plus one */
countcomma (treestr, &num_comma);
num_comma++;
for (i = 0; i < rcategs; i++) {
for (j = 0; j < categs; j++) {
/* Free the stuff allocated assuming bifurcations */
free (tbl[i][j]->ww);
free (tbl[i][j]->zz);
free (tbl[i][j]->wwzz);
free (tbl[i][j]->vvzz);
/* Then allocate for worst-case multifurcations */
tbl[i][j]->ww = (double *) Malloc( num_comma * sizeof (double));
tbl[i][j]->zz = (double *) Malloc( num_comma * sizeof (double));
tbl[i][j]->wwzz = (double *) Malloc( num_comma * sizeof (double));
tbl[i][j]->vvzz = (double *) Malloc( num_comma * sizeof (double));
}
}
} /* inittable_for_usertree */
static void freetable(void)
{
long i, j;
for (i = 0; i < rcategs; i++) {
for (j = 0; j < categs; j++) {
free(tbl[i][j]->ww);
free(tbl[i][j]->zz);
free(tbl[i][j]->wwzz);
free(tbl[i][j]->vvzz);
}
}
for (i = 0; i < rcategs; i++) {
for (j = 0; j < categs; j++)
free(tbl[i][j]);
free(tbl[i]);
}
free(tbl);
}
static void inittable(void)
{
/* Define a lookup table. Precompute values and print them out in tables */
long i, j;
double sumrates;
tbl = (valrec ***) Malloc( rcategs * sizeof(valrec **));
for (i = 0; i < rcategs; i++) {
tbl[i] = (valrec **) Malloc( categs*sizeof(valrec *));
for (j = 0; j < categs; j++)
tbl[i][j] = (valrec *) Malloc( sizeof(valrec));
}
for (i = 0; i < rcategs; i++) {
for (j = 0; j < categs; j++) {
tbl[i][j]->rat = rrate[i]*rate[j];
tbl[i][j]->ratxi = tbl[i][j]->rat * xi;
tbl[i][j]->ratxv = tbl[i][j]->rat * xv;
/* Allocate assuming bifurcations, will be changed later if
neccesarry (i.e. there's a user tree) */
tbl[i][j]->ww = (double *) Malloc( 2 * sizeof (double));
tbl[i][j]->zz = (double *) Malloc( 2 * sizeof (double));
tbl[i][j]->wwzz = (double *) Malloc( 2 * sizeof (double));
tbl[i][j]->vvzz = (double *) Malloc( 2 * sizeof (double));
}
}
sumrates = 0.0;
for (i = 0; i < endsite; i++) {
for (j = 0; j < rcategs; j++)
sumrates += aliasweight[i] * probcat[j]
* tbl[j][category[alias[i] - 1] - 1]->rat;
}
sumrates /= (double)sites;
for (i = 0; i < rcategs; i++)
for (j = 0; j < categs; j++) {
tbl[i][j]->rat /= sumrates;
tbl[i][j]->ratxi /= sumrates;
tbl[i][j]->ratxv /= sumrates;
}
if(jumb > 1)
return;
if (gama || invar) {
fprintf(outfile, "\nDiscrete approximation to gamma distributed rates\n");
fprintf(outfile,
" Coefficient of variation of rates = %f (alpha = %f)\n", cv, alpha);
}
if (rcategs > 1) {
fprintf(outfile, "\nState in HMM Rate of change Probability\n\n");
for (i = 0; i < rcategs; i++)
if (probcat[i] < 0.0001)
fprintf(outfile, "%9ld%16.3f%20.6f\n", i+1, rrate[i], probcat[i]);
else if (probcat[i] < 0.001)
fprintf(outfile, "%9ld%16.3f%19.5f\n", i+1, rrate[i], probcat[i]);
else if (probcat[i] < 0.01)
fprintf(outfile, "%9ld%16.3f%18.4f\n", i+1, rrate[i], probcat[i]);
else
fprintf(outfile, "%9ld%16.3f%17.3f\n", i+1, rrate[i], probcat[i]);
putc('\n', outfile);
if (auto_) {
fprintf(outfile,
"Expected length of a patch of sites having the same rate = %8.3f\n",
1/lambda);
putc('\n', outfile);
}
}
if (categs > 1) {
fprintf(outfile, "\nSite category Rate of change\n\n");
for (i = 0; i < categs; i++)
fprintf(outfile, "%9ld%16.3f\n", i+1, rate[i]);
fprintf(outfile, "\n\n");
}
} /* inittable */
static void alloc_nvd(long num_sibs, nuview_data *local_nvd)
{
/* Allocate blocks of memory appropriate for the number of siblings
a given node has */
local_nvd->yy = (double *) Malloc( num_sibs * sizeof (double));
local_nvd->wwzz = (double *) Malloc( num_sibs * sizeof (double));
local_nvd->vvzz = (double *) Malloc( num_sibs * sizeof (double));
local_nvd->vzsumr = (double *) Malloc( num_sibs * sizeof (double));
local_nvd->vzsumy = (double *) Malloc( num_sibs * sizeof (double));
local_nvd->sum = (double *) Malloc( num_sibs * sizeof (double));
local_nvd->sumr = (double *) Malloc( num_sibs * sizeof (double));
local_nvd->sumy = (double *) Malloc( num_sibs * sizeof (double));
local_nvd->xx = (sitelike *) Malloc( num_sibs * sizeof (sitelike));
} /* alloc_nvd */
static void free_nvd(nuview_data *local_nvd)
{
/* The natural complement to the alloc version */
free (local_nvd->yy);
free (local_nvd->wwzz);
free (local_nvd->vvzz);
free (local_nvd->vzsumr);
free (local_nvd->vzsumy);
free (local_nvd->sum);
free (local_nvd->sumr);
free (local_nvd->sumy);
free (local_nvd->xx);
} /* free_nvd */
static boolean nuview(node *p)
{
/* Recursively update summary data for subtree rooted at p. Returns true if
* view has changed. */
long i, j, k, l, num_sibs = 0, sib_index;
nuview_data *local_nvd;
node *q;
node *sib_ptr, *sib_back_ptr;
sitelike p_xx;
double lw;
double correction;
double maxx;
assert(p != NULL);
if ( p == NULL ) return false;
if ( p->tip ) return false; /* Tips do not need to be initialized */
for (q = p->next; q != p; q = q->next) {
num_sibs++;
if ( q->back != NULL && !q->tip) {
if ( nuview(q->back) )
p->initialized = false;
}
}
if ( p->initialized )
return false;
/* At this point, all views downstream should be initialized.
* If not, we have a problem. */
/*assert( invalid_descendant_view(p) == NULL );*/
/* Allocate the structure and blocks therein for variables used in
this function */
local_nvd = (nuview_data *) Malloc( sizeof (nuview_data));
alloc_nvd (num_sibs, local_nvd);
/* Loop 1: makes assignments to tbl based on some combination of
what's already in tbl and the children's value of v */
sib_ptr = p;
for (sib_index=0; sib_index < num_sibs; sib_index++) {
sib_ptr = sib_ptr->next;
sib_back_ptr = sib_ptr->back;
if (sib_back_ptr != NULL)
lw = -fabs(p->tyme - sib_back_ptr->tyme);
else
lw = 0.0;
for (i = 0; i < rcategs; i++)
for (j = 0; j < categs; j++) {
tbl[i][j]->ww[sib_index] = exp(tbl[i][j]->ratxi * lw);
tbl[i][j]->zz[sib_index] = exp(tbl[i][j]->ratxv * lw);
tbl[i][j]->wwzz[sib_index] = tbl[i][j]->ww[sib_index] * tbl[i][j]->zz[sib_index];
tbl[i][j]->vvzz[sib_index] = (1.0 - tbl[i][j]->ww[sib_index]) *
tbl[i][j]->zz[sib_index];
}
}
/* Loop 2: */
for (i = 0; i < endsite; i++) {
correction = 0;
maxx = 0;
k = category[alias[i]-1] - 1;
for (j = 0; j < rcategs; j++) {
/* Loop 2.1 */
sib_ptr = p;
for (sib_index=0; sib_index < num_sibs; sib_index++) {
sib_ptr = sib_ptr->next;
sib_back_ptr = sib_ptr->back;
local_nvd->wwzz[sib_index] = tbl[j][k]->wwzz[sib_index];
local_nvd->vvzz[sib_index] = tbl[j][k]->vvzz[sib_index];
local_nvd->yy[sib_index] = 1.0 - tbl[j][k]->zz[sib_index];
if (sib_back_ptr != NULL) {
memcpy(local_nvd->xx[sib_index],
sib_back_ptr->x[i][j],
sizeof(sitelike));
if ( j == 0)
correction += sib_back_ptr->underflows[i];
}
else {
local_nvd->xx[sib_index][0] = 1.0;
local_nvd->xx[sib_index][(long)C - (long)A] = 1.0;
local_nvd->xx[sib_index][(long)G - (long)A] = 1.0;
local_nvd->xx[sib_index][(long)T - (long)A] = 1.0;
}
}
/* Loop 2.2 */
for (sib_index=0; sib_index < num_sibs; sib_index++) {
local_nvd->sum[sib_index] =
local_nvd->yy[sib_index] *
(freqa * local_nvd->xx[sib_index][(long)A] +
freqc * local_nvd->xx[sib_index][(long)C] +
freqg * local_nvd->xx[sib_index][(long)G] +
freqt * local_nvd->xx[sib_index][(long)T]);
local_nvd->sumr[sib_index] =
freqar * local_nvd->xx[sib_index][(long)A] +
freqgr * local_nvd->xx[sib_index][(long)G];
local_nvd->sumy[sib_index] =
freqcy * local_nvd->xx[sib_index][(long)C] +
freqty * local_nvd->xx[sib_index][(long)T];
local_nvd->vzsumr[sib_index] =
local_nvd->vvzz[sib_index] * local_nvd->sumr[sib_index];
local_nvd->vzsumy[sib_index] =
local_nvd->vvzz[sib_index] * local_nvd->sumy[sib_index];
}
/* Initialize to one, multiply incremental values for every
sibling a node has */
p_xx[(long)A] = 1 ;
p_xx[(long)C] = 1 ;
p_xx[(long)G] = 1 ;
p_xx[(long)T] = 1 ;
for (sib_index=0; sib_index < num_sibs; sib_index++) {
p_xx[(long)A] *=
local_nvd->sum[sib_index] +
local_nvd->wwzz[sib_index] *
local_nvd->xx[sib_index][(long)A] +
local_nvd->vzsumr[sib_index];
p_xx[(long)C] *=
local_nvd->sum[sib_index] +
local_nvd->wwzz[sib_index] *
local_nvd->xx[sib_index][(long)C] +
local_nvd->vzsumy[sib_index];
p_xx[(long)G] *=
local_nvd->sum[sib_index] +
local_nvd->wwzz[sib_index] *
local_nvd->xx[sib_index][(long)G] +
local_nvd->vzsumr[sib_index];
p_xx[(long)T] *=
local_nvd->sum[sib_index] +
local_nvd->wwzz[sib_index] *
local_nvd->xx[sib_index][(long)T] +
local_nvd->vzsumy[sib_index];
}
for ( l = 0 ; l < ((long)T - (long)A + 1 ) ; l++ ) {
if ( p_xx[l] > maxx )
maxx = p_xx[l];
}
/* And the final point of this whole function: */
memcpy(p->x[i][j], p_xx, sizeof(sitelike));
}
p->underflows[i] = 0;
if ( maxx < MIN_DOUBLE)
fix_x(p, i, maxx,rcategs);
p->underflows[i] += correction;
}
free_nvd (local_nvd);
free (local_nvd);
p->initialized = true;
return true;
} /* nuview */
static double dnamlk_evaluate(node *p)
{ /* Evaluate and return the log likelihood of the current tree
* as seen from the branch from p to p->back. If p is the root node,
* the first child branch is used instead. Views are updated as needed. */
contribarr tterm;
static contribarr like, nulike, clai;
double sum, sum2, sumc=0, y, lz, y1, z1zz, z1yy,
prod12, prod1, prod2, prod3, sumterm, lterm;
long i, j, k, lai;
node *q, *r;
double *x1, *x2; /* pointers to sitelike elements in node->x */
sum = 0.0;
assert( all_tymes_valid(curtree.root, 0.0, false) );
/* Root node has no branch, so use branch to first child */
if (p == curtree.root)
p = p->next;
r = p;
q = p->back;
nuview(r);
nuview(q);
y = fabs(r->tyme - q->tyme);
lz = -y;
for (i = 0; i < rcategs; i++)
for (j = 0; j < categs; j++) {
tbl[i][j]->orig_zz = exp(tbl[i][j]->ratxi * lz);
tbl[i][j]->z1 = exp(tbl[i][j]->ratxv * lz);
tbl[i][j]->z1zz = tbl[i][j]->z1 * tbl[i][j]->orig_zz;
tbl[i][j]->z1yy = tbl[i][j]->z1 - tbl[i][j]->z1zz;
}
for (i = 0; i < endsite; i++) {
k = category[alias[i]-1] - 1;
for (j = 0; j < rcategs; j++) {
if (y > 0.0) {
y1 = 1.0 - tbl[j][k]->z1;
z1zz = tbl[j][k]->z1zz;
z1yy = tbl[j][k]->z1yy;
} else {
y1 = 0.0;
z1zz = 1.0;
z1yy = 0.0;
}
x1 = r->x[i][j];
prod1 = freqa * x1[0] + freqc * x1[(long)C - (long)A] +
freqg * x1[(long)G - (long)A] + freqt * x1[(long)T - (long)A];
x2 = q->x[i][j];
prod2 = freqa * x2[0] + freqc * x2[(long)C - (long)A] +
freqg * x2[(long)G - (long)A] + freqt * x2[(long)T - (long)A];
prod3 = (x1[0] * freqa + x1[(long)G - (long)A] * freqg) *
(x2[0] * freqar + x2[(long)G - (long)A] * freqgr) +
(x1[(long)C - (long)A] * freqc + x1[(long)T - (long)A] * freqt) *
(x2[(long)C - (long)A] * freqcy + x2[(long)T - (long)A] * freqty);
prod12 = freqa * x1[0] * x2[0] +
freqc * x1[(long)C - (long)A] * x2[(long)C - (long)A] +
freqg * x1[(long)G - (long)A] * x2[(long)G - (long)A] +
freqt * x1[(long)T - (long)A] * x2[(long)T - (long)A];
tterm[j] = z1zz * prod12 + z1yy * prod3 + y1 * prod1 * prod2;
}
sumterm = 0.0;
for (j = 0; j < rcategs; j++)
sumterm += probcat[j] * tterm[j];
lterm = log(sumterm) + p->underflows[i] + q->underflows[i];
for (j = 0; j < rcategs; j++)
clai[j] = tterm[j] / sumterm;
memcpy(contribution[i], clai, sizeof(contribarr));
if (!auto_ && usertree && (which <= shimotrees))
l0gf[which - 1][i] = lterm;
sum += aliasweight[i] * lterm;
}
if (auto_) {
for (j = 0; j < rcategs; j++)
like[j] = 1.0;
for (i = 0; i < sites; i++) {
sumc = 0.0;
for (k = 0; k < rcategs; k++)
sumc += probcat[k] * like[k];
sumc *= lambda;
if ((ally[i] > 0) && (location[ally[i]-1] > 0)) {
lai = location[ally[i] - 1];
memcpy(clai, contribution[lai - 1], sizeof(contribarr));
for (j = 0; j < rcategs; j++)
nulike[j] = ((1.0 - lambda) * like[j] + sumc) * clai[j];
} else {
for (j = 0; j < rcategs; j++)
nulike[j] = ((1.0 - lambda) * like[j] + sumc);
}
memcpy(like, nulike, sizeof(contribarr));
}
sum2 = 0.0;
for (i = 0; i < rcategs; i++)
sum2 += probcat[i] * like[i];
sum += log(sum2);
}
curtree.likelihood = sum;
if (auto_ || !usertree)
return sum;
if(which <= shimotrees)
l0gl[which - 1] = sum;
if (which == 1) {
maxwhich = 1;
maxlogl = sum;
return sum;
}
if (sum > maxlogl) {
maxwhich = which;
maxlogl = sum;
}
return sum;
} /* dnamlk_evaluate */
static boolean update(node *p)
{
/* Conditionally optimize tyme at a node. Return true if successful. */
if (p == NULL)
return false;
if ( (!usertree) || (usertree && !lngths) )
return makenewv(p);
return false;
} /* update */
static boolean smooth(node *p)
{
node *q = NULL;
boolean success;
if (p == NULL)
return false;
if (p->tip)
return false;
/* optimize tyme here */
success = update(p);
if (smoothit || polishing) {
for (q = p->next; q != p; q = q->next) {
/* smooth subtrees */
success = smooth(q->back) || success;
/* optimize tyme again after each subtree */
success = update(p) || success;
}
}
return success;
} /* smooth */
static void restoradd(node *below, node *newtip, node *newfork, double prevtyme)
{
/* restore "new" tip and fork to place "below". restore tymes */
/* assumes bifurcation */
hookup(newfork, below->back);
hookup(newfork->next, below);
hookup(newtip, newfork->next->next);
curtree.nodep[newfork->index-1] = newfork;
setnodetymes(newfork,prevtyme);
} /* restoradd */
static void dnamlk_add(node *below, node *newtip, node *newfork)
{
/* inserts the nodes newfork and its descendant, newtip, into the tree. */
long i;
node *p;
node *above;
double newtyme;
boolean success;
assert( all_tymes_valid(curtree.root, 0.98*MIN_BRANCH_LENGTH, false) );
/*assert( floating_fork(newfork) );*/
assert( newtip->back == NULL );
/* Get parent nodelets */
below = pnode(&curtree, below);
newfork = pnode(&curtree, newfork);
newtip = pnode(&curtree, newtip);
/* Join above node to newfork */
if (below->back == NULL)
newfork->back = NULL;
else {
above = below->back;
/* unhookup(below, above); */
hookup(newfork, above);
}
/* Join below to newfork->next->next */
hookup(below, newfork->next->next);
/* Join newtip to newfork->next */
hookup(newfork->next, newtip);
/* Move root if inserting there */
if (curtree.root == below)
curtree.root = newfork;
/* p = child with lowest tyme */
p = newtip->tyme < below->tyme ? newtip : below;
/* If not at root, set newfork tyme to average below/above */
if (newfork->back != NULL) {
if (p->tyme > newfork->back->tyme)
newtyme = (p->tyme + newfork->back->tyme) / 2.0;
else
newtyme = p->tyme - INSERT_MIN_TYME;
if (p->tyme - newtyme < MIN_BRANCH_LENGTH)
newtyme = p->tyme - MIN_BRANCH_LENGTH;
setnodetymes(newfork, newtyme);
/* Now move from newfork to root, setting parent tymes older than children
* by at least MIN_BRANCH_LENGTH */
p = newfork;
while (p != curtree.root) {
if (p->back->tyme > p->tyme - MIN_BRANCH_LENGTH)
setnodetymes(p->back, p->tyme - MIN_BRANCH_LENGTH);
else
break;
/* get parent node */
p = pnode(&curtree, p->back);
}
} else { /* root == newfork */
/* make root 2x older */
setnodetymes(newfork, p->tyme - 2*INSERT_MIN_TYME);
}
assert( all_tymes_valid(curtree.root, 0.98*MIN_BRANCH_LENGTH, false) );
/* Adjust branch lengths throughout */
for ( i = 1; i < smoothings; i++ ) {
success = smooth(newfork);
success = smooth(newfork->back) || success;
if ( !success ) break;
}
} /* dnamlk_add */
static void dnamlk_re_move(node **item, node **fork, boolean tempadd)
{
/* removes nodes *item and its parent (returned in *fork), from the tree.
the new descendant of fork's ancestor is made to be fork's descendant other
than item. Item must point to node*, but *fork is not read */
node *p, *q;
long i;
boolean success;
if ((*item)->back == NULL) {
*fork = NULL;
return;
}
*item = curtree.nodep[(*item)->index-1];
*fork = curtree.nodep[(*item)->back->index - 1];
if (curtree.root == *fork) {
if (*item == (*fork)->next->back)
curtree.root = (*fork)->next->next->back;
else
curtree.root = (*fork)->next->back;
}
p = (*item)->back->next->back;
q = (*item)->back->next->next->back;
if (p != NULL)
p->back = q;
if (q != NULL)
q->back = p;
(*fork)->back = NULL;
p = (*fork)->next;
while (p != *fork) {
p->back = NULL;
p = p->next;
}
(*item)->back = NULL;
inittrav(p);
inittrav(q);
if (tempadd)
return;
for ( i = 1; i <= smoothings; i++ ) {
success = smooth(q);
if ( smoothit )
success = smooth(q->back) || success;
if ( !success ) break;
}
} /* dnamlk_re_move */
static void tryadd(node *p, node **item, node **nufork)
{ /* temporarily adds one fork and one tip to the tree.
if the location where they are added yields greater
likelihood than other locations tested up to that
time, then keeps that location as there */
if ( !global2 )
save_tymes(&curtree,tymes);
dnamlk_add(p, *item, *nufork);
like = dnamlk_evaluate(p);
if (lastsp) {
if (like >= bestree.likelihood || bestree.likelihood == UNDEFINED) {
copy_(&curtree, &bestree, nonodes, rcategs);
if ( global2 )
/* To be restored in maketree() */
save_tymes(&curtree,tymes);
}
}
if (like > bestyet || bestyet == UNDEFINED) {
bestyet = like;
there = p;
}
dnamlk_re_move(item, nufork, true);
if ( !global2 ) {
restore_tymes(&curtree,tymes);
}
} /* tryadd */
static void addpreorder(node *p, node *item_, node *nufork_, boolean contin,
boolean continagain)
{
/* Traverse tree, adding item at different locations until we
* find a better likelihood. Afterwards, global 'there' will be
* set to the best add location, or will be left alone if no
* better could be found. */
node *item, *nufork;
item = item_;
nufork = nufork_;
if (p == NULL)
return;
tryadd(p, &item, &nufork);
contin = continagain;
if ((!p->tip) && contin) {
/* assumes bifurcation (OK) */
addpreorder(p->next->back, item, nufork, contin, continagain);
addpreorder(p->next->next->back, item, nufork, contin, continagain);
}
} /* addpreorder */
static boolean tryrearr(node *p)
{
/* evaluates one rearrangement of the tree.
if the new tree has greater likelihood than the old
keeps the new tree and returns true.
otherwise, restores the old tree and returns false. */
node *forknode; /* parent fork of p */
node *frombelow; /* other child of forknode */
node *whereto; /* parent fork of forknode */
double oldlike; /* likelihood before rearrangement */
double prevtyme; /* forknode->tyme before rearrange */
double like_delta; /* improvement in likelihood */
boolean wasonleft; /* true if p first child of forknode */
if (p == curtree.root)
return false;
/* forknode = parent fork of p */
forknode = curtree.nodep[p->back->index - 1];
if (forknode == curtree.root)
return false;
oldlike = bestyet;
prevtyme = forknode->tyme;
/* assumes bifurcation (OK) */
/* frombelow = other child of forknode (not p) */
if (forknode->next->back == p) {
frombelow = forknode->next->next->back;
wasonleft = true;
}
else {
frombelow = forknode->next->back;
wasonleft = false;
}
whereto = curtree.nodep[forknode->back->index - 1];
/* remove forknode and p */
dnamlk_re_move(&p, &forknode, true);
/* add p and forknode as parent of whereto */
dnamlk_add(whereto, p, forknode);
like = dnamlk_evaluate(p);
like_delta = like - oldlike;
if ( like_delta < LIKE_EPSILON && oldlike != UNDEFINED) {
dnamlk_re_move(&p, &forknode, true);
restoradd(frombelow, p, forknode, prevtyme);
if (wasonleft && (forknode->next->next->back == p)) {
hookup (forknode->next->back, forknode->next->next);
hookup (forknode->next, p);
}
curtree.likelihood = oldlike;
/* assumes bifurcation (OK) */
inittrav(forknode);
inittrav(forknode->next);
inittrav(forknode->next->next);
return false;
} else {
bestyet = like;
}
return true;
} /* tryrearr */
static boolean repreorder(node *p)
{
/* traverses a binary tree, calling function tryrearr
at a node before calling tryrearr at its descendants.
Returns true the first time rearrangement increases the
tree's likelihood. */
if (p == NULL)
return false;
if ( !tryrearr(p) )
return false;
if (p->tip)
return true;
/* assumes bifurcation */
if ( !repreorder(p->next->back) )
return false;
if ( !repreorder(p->next->next->back) )
return false;
return true;
} /* repreorder */
static void rearrange(node **r)
{
/* traverses the tree (preorder), finding any local
rearrangement which increases the likelihood.
if traversal succeeds in increasing the tree's
likelihood, function rearrange runs traversal again */
while ( repreorder(*r) )
/* continue */;
} /* rearrange */
static void initdnamlnode(node **p, node **grbg, node *q, long len, long nodei,
long *ntips, long *parens, initops whichinit,
pointarray treenode, pointarray nodep, Char *str, Char *ch,
char** treestr)
{
/* Initializes each node as it is read from user tree by treeread().
* whichinit specifies which type of initialization is to be done.
*/
boolean minusread;
double valyew, divisor;
switch (whichinit) {
case bottom:
gnu(grbg, p);
(*p)->index = nodei;
(*p)->tip = false;
malloc_pheno((*p), endsite, rcategs);
nodep[(*p)->index - 1] = (*p);
break;
case nonbottom:
gnu(grbg, p);
malloc_pheno(*p, endsite, rcategs);
(*p)->index = nodei;
break;
case tip:
match_names_to_data (str, nodep, p, spp);
break;
case iter:
(*p)->initialized = false;
/* Initial branch lengths start at 0.0. tymetrav() enforces
* MIN_BRANCH_LENGTH */
(*p)->v = 0.0;
(*p)->iter = true;
if ((*p)->back != NULL)
(*p)->back->iter = true;
break;
case length:
processlength(&valyew, &divisor, ch, &minusread, treestr, parens);
(*p)->v = valyew / divisor / fracchange;
(*p)->iter = false;
if ((*p)->back != NULL) {
(*p)->back->v = (*p)->v;
(*p)->back->iter = false;
}
break;
case hslength:
break;
case hsnolength:
if (usertree && lengthsopt && lngths) {
printf("Warning: one or more lengths not defined in user tree number %ld.\n", which);
printf("DNAMLK will attempt to optimize all branch lengths.\n\n");
lngths = false;
}
break;
case treewt:
break;
case unittrwt:
break;
}
} /* initdnamlnode */
static boolean tymetrav(node *p)
{
/* Recursively convert branch lengths to node tymes. Returns the maximum
* branch length p's parent can have, which is p->tyme - max(p->v,
* MIN_BRANCH_LENGTH) */
node *q;
double xmax;
double x;
xmax = 0.0;
if (!p->tip) {
for (q = p->next; q != p; q = q->next) {
x = tymetrav(q->back);
if (xmax > x)
xmax = x;
}
} else {
x = 0.0;
}
setnodetymes(p,xmax);
if (p->v < MIN_BRANCH_LENGTH)
return xmax - MIN_BRANCH_LENGTH;
else
return xmax - p->v;
} /* tymetrav */
static void reconstr(node *p, long n)
{
/* reconstruct and print out base at site n+1 at node p */
long i, j, k, m, first, second, num_sibs;
double f, sum, xx[4];
node *q;
if ((ally[n] == 0) || (location[ally[n]-1] == 0))
putc('.', outfile);
else {
j = location[ally[n]-1] - 1;
for (i = 0; i < 4; i++) {
f = p->x[j][mx-1][i];
num_sibs = count_sibs(p);
q = p;
for (k = 0; k < num_sibs; k++) {
q = q->next;
f *= q->x[j][mx-1][i];
}
f = sqrt(f);
xx[i] = f;
}
xx[0] *= freqa;
xx[1] *= freqc;
xx[2] *= freqg;
xx[3] *= freqt;
sum = xx[0]+xx[1]+xx[2]+xx[3];
for (i = 0; i < 4; i++)
xx[i] /= sum;
first = 0;
for (i = 1; i < 4; i++)
if (xx [i] > xx[first])
first = i;
if (first == 0)
second = 1;
else
second = 0;
for (i = 0; i < 4; i++)
if ((i != first) && (xx[i] > xx[second]))
second = i;
m = 1 << first;
if (xx[first] < 0.4999995)
m = m + (1 << second);
if (xx[first] > 0.95)
putc(toupper((int)basechar[m - 1]), outfile);
else
putc(basechar[m - 1], outfile);
if (rctgry && rcategs > 1)
mx = mp[n][mx - 1];
else
mx = 1;
}
} /* reconstr */
static void rectrav(node *p, long m, long n)
{
/* print out segment of reconstructed sequence for one branch */
long num_sibs, i;
node *sib_ptr;
putc(' ', outfile);
if (p->tip) {
for (i = 0; i < nmlngth; i++)
putc(nayme[p->index-1][i], outfile);
} else
fprintf(outfile, "%4ld ", p->index - spp);
fprintf(outfile, " ");
mx = mx0;
for (i = m; i <= n; i++) {
if ((i % 10 == 0) && (i != m))
putc(' ', outfile);
if (p->tip)
putc(y[p->index-1][i], outfile);
else
reconstr(p, i);
}
putc('\n', outfile);
if (!p->tip) {
num_sibs = count_sibs(p);
sib_ptr = p;
for (i = 0; i < num_sibs; i++) {
sib_ptr = sib_ptr->next;
rectrav(sib_ptr->back, m, n);
}
}
mx1 = mx;
} /* rectrav */
static void summarize(FILE *fp)
{
long i, j, mm;
double mode, sum;
double like[maxcategs], nulike[maxcategs];
double **marginal;
mp = (long **)Malloc(sites * sizeof(long *));
for (i = 0; i <= sites-1; ++i)
mp[i] = (long *)Malloc(sizeof(long)*rcategs);
fprintf(fp, "\nLn Likelihood = %11.5f\n\n", curtree.likelihood);
fprintf(fp, " Ancestor Node Node Height Length\n");
fprintf(fp, " -------- ---- ---- ------ ------\n");
mlk_describe(fp, &curtree, fracchange);
putc('\n', fp);
if (rctgry && rcategs > 1) {
for (i = 0; i < rcategs; i++)
like[i] = 1.0;
for (i = sites - 1; i >= 0; i--) {
sum = 0.0;
for (j = 0; j < rcategs; j++) {
nulike[j] = (lambda1 + lambda * probcat[j]) * like[j];
mp[i][j] = j + 1;
for (k = 1; k <= rcategs; k++) {
if (k != j + 1) {
if (lambda * probcat[k - 1] * like[k - 1] > nulike[j]) {
nulike[j] = lambda * probcat[k - 1] * like[k - 1];
mp[i][j] = k;
}
}
}
if ((ally[i] > 0) && (location[ally[i]-1] > 0))
nulike[j] *= contribution[location[ally[i] - 1] - 1][j];
sum += nulike[j];
}
for (j = 0; j < rcategs; j++)
nulike[j] /= sum;
memcpy(like, nulike, rcategs * sizeof(double));
}
mode = 0.0;
mx = 1;
for (i = 1; i <= rcategs; i++) {
if (probcat[i - 1] * like[i - 1] > mode) {
mx = i;
mode = probcat[i - 1] * like[i - 1];
}
}
mx0 = mx;
fprintf(fp,
"Combination of categories that contributes the most to the likelihood:\n\n");
for (i = 1; i <= nmlngth + 3; i++)
putc(' ', fp);
for (i = 1; i <= sites; i++) {
fprintf(fp, "%ld", mx);
if (i % 10 == 0)
putc(' ', fp);
if (i % 60 == 0 && i != sites) {
putc('\n', fp);
for (j = 1; j <= nmlngth + 3; j++)
putc(' ', fp);
}
mx = mp[i - 1][mx - 1];
}
fprintf(fp, "\n\n");
marginal = (double **) Malloc( sites*sizeof(double *));
for (i = 0; i < sites; i++)
marginal[i] = (double *) Malloc( rcategs*sizeof(double));
for (i = 0; i < rcategs; i++)
like[i] = 1.0;
for (i = sites - 1; i >= 0; i--) {
sum = 0.0;
for (j = 0; j < rcategs; j++) {
nulike[j] = (lambda1 + lambda * probcat[j]) * like[j];
for (k = 1; k <= rcategs; k++) {
if (k != j + 1)
nulike[j] += lambda * probcat[k - 1] * like[k - 1];
}
if ((ally[i] > 0) && (location[ally[i]-1] > 0))
nulike[j] *= contribution[location[ally[i] - 1] - 1][j];
sum += nulike[j];
}
for (j = 0; j < rcategs; j++) {
nulike[j] /= sum;
marginal[i][j] = nulike[j];
}
memcpy(like, nulike, rcategs * sizeof(double));
}
for (i = 0; i < rcategs; i++)
like[i] = 1.0;
for (i = 0; i < sites; i++) {
sum = 0.0;
for (j = 0; j < rcategs; j++) {
nulike[j] = (lambda1 + lambda * probcat[j]) * like[j];
for (k = 1; k <= rcategs; k++) {
if (k != j + 1)
nulike[j] += lambda * probcat[k - 1] * like[k - 1];
}
marginal[i][j] *= like[j] * probcat[j];
sum += nulike[j];
}
for (j = 0; j < rcategs; j++)
nulike[j] /= sum;
memcpy(like, nulike, rcategs * sizeof(double));
sum = 0.0;
for (j = 0; j < rcategs; j++)
sum += marginal[i][j];
for (j = 0; j < rcategs; j++)
marginal[i][j] /= sum;
}
fprintf( fp, "Most probable category at each site if > 0.95 probability "
"(\".\" otherwise)\n\n" );
for (i = 1; i <= nmlngth + 3; i++)
putc(' ', fp);
for (i = 0; i < sites; i++) {
mm = 0;
sum = 0.0;
for (j = 0; j < rcategs; j++)
if (marginal[i][j] > sum) {
sum = marginal[i][j];
mm = j;
}
if (sum >= 0.95)
fprintf(fp, "%ld", mm+1);
else
putc('.', fp);
if ((i+1) % 60 == 0) {
if (i != 0) {
putc('\n', fp);
for (j = 1; j <= nmlngth + 3; j++)
putc(' ', fp);
}
}
else if ((i+1) % 10 == 0)
putc(' ', fp);
}
putc('\n', fp);
for (i = 0; i < sites; i++)
free(marginal[i]);
free(marginal);
}
putc('\n', fp);
putc('\n', fp);
if (hypstate) {
fprintf(fp, "Probable sequences at interior nodes:\n\n");
fprintf(fp, " node ");
for (i = 0; (i < 13) && (i < ((sites + (sites-1)/10 - 39) / 2)); i++)
putc(' ', fp);
fprintf(fp, "Reconstructed sequence (caps if > 0.95)\n\n");
if (!rctgry || (rcategs == 1))
mx0 = 1;
for (i = 0; i < sites; i += 60) {
k = i + 59;
if (k >= sites)
k = sites - 1;
rectrav(curtree.root, i, k);
putc('\n', fp);
mx0 = mx1;
}
}
for (i = 0; i < sites; ++i)
free(mp[i]);
free(mp);
} /* summarize */
static void dnamlk_treeout(node *p)
{
/* write out file with representation of final tree */
node *sib_ptr;
long i, n, w, num_sibs;
Char c;
double x;
if (p->tip) {
n = 0;
for (i = 1; i <= nmlngth; i++) {
if (nayme[p->index - 1][i - 1] != ' ')
n = i;
}
for (i = 0; i < n; i++) {
c = nayme[p->index - 1][i];
if (c == ' ')
c = '_';
putc(c, outtree);
}
col += n;
} else {
sib_ptr = p;
num_sibs = count_sibs(p);
putc('(', outtree);
col++;
for (i=0; i < (num_sibs - 1); i++) {
sib_ptr = sib_ptr->next;
dnamlk_treeout(sib_ptr->back);
putc(',', outtree);
col++;
if (col > 55) {
putc('\n', outtree);
col = 0;
}
}
sib_ptr = sib_ptr->next;
dnamlk_treeout(sib_ptr->back);
putc(')', outtree);
col++;
}
if (p == curtree.root) {
fprintf(outtree, ";\n");
return;
}
x = fracchange * (p->tyme - curtree.nodep[p->back->index - 1]->tyme);
if (x > 0.0)
w = (long)(0.4342944822 * log(x));
else if (x == 0.0)
w = 0;
else
w = (long)(0.4342944822 * log(-x)) + 1;
if (w < 0)
w = 0;
fprintf(outtree, ":%*.5f", (int)(w + 7), x);
col += w + 8;
} /* dnamlk_treeout */
static void init_tymes(node *p, double minlength)
{
/* Set all node tymes closest to the tips but with no branches shorter than
* minlength */
long i, num_sibs;
node *sib_ptr, *sib_back_ptr;
/* traverse to set up times in subtrees */
if (p->tip)
return;
sib_ptr = p;
num_sibs = count_sibs(p);
for (i=0 ; i < num_sibs; i++) {
sib_ptr = sib_ptr->next;
sib_back_ptr = sib_ptr->back;
init_tymes(sib_back_ptr, minlength);
}
/* set time at this node */
setnodetymes(p, min_child_tyme(p) - minlength);
} /* init_tymes */
static void treevaluate(void)
{
/* evaluate likelihood of tree, after iterating branch lengths */
long i;
if ( !usertree || (usertree && !lngths) ) {
polishing = true;
smoothit = true;
for (i = 0; i < smoothings; ) {
if ( !smooth(curtree.root) )
i++;
}
}
dnamlk_evaluate(curtree.root);
} /* treevaluate */
static void maketree(void)
{
/* constructs a binary tree from the pointers in curtree.nodep,
adds each node at location which yields highest likelihood
then rearranges the tree for greatest likelihood */
long i, j;
node *item, *nufork, *dummy, *q, *root=NULL;
boolean succeded, dummy_haslengths, dummy_first, goteof;
long max_nonodes; /* Maximum number of nodes required to
* express all species in a bifurcating tree
* */
long nextnode;
pointarray dummy_treenode=NULL;
double oldbest;
node *tmp;
char* treestr;
inittable();
if (!usertree) {
for (i = 1; i <= spp; i++)
enterorder[i - 1] = i;
if (jumble)
randumize(seed, enterorder);
curtree.root = curtree.nodep[spp];
curtree.root->back = NULL;
for (i = 0; i < spp; i++)
curtree.nodep[i]->back = NULL;
for (i = spp; i < nonodes; i++) {
q = curtree.nodep[i];
q->back = NULL;
while ((q = q->next) != curtree.nodep[i])
q->back = NULL;
}
polishing = false;
dnamlk_add(curtree.nodep[enterorder[0] - 1], curtree.nodep[enterorder[1] - 1],
curtree.nodep[spp]);
if (progress) {
printf("\nAdding species:\n");
writename(0, 2, enterorder);
#ifdef WIN32
phyFillScreenColor();
#endif
}
lastsp = false;
smoothit = false;
for (i = 3; i <= spp; i++) {
bestree.likelihood = UNDEFINED;
bestyet = UNDEFINED;
there = curtree.root;
item = curtree.nodep[enterorder[i - 1] - 1];
nufork = curtree.nodep[spp + i - 2];
lastsp = (i == spp);
addpreorder(curtree.root, item, nufork, true, true);
dnamlk_add(there, item, nufork);
like = dnamlk_evaluate(curtree.root);
copy_(&curtree, &bestree, nonodes, rcategs);
rearrange(&curtree.root);
if (curtree.likelihood > bestree.likelihood) {
copy_(&curtree, &bestree, nonodes, rcategs);
}
if (progress) {
writename(i - 1, 1, enterorder);
#ifdef WIN32
phyFillScreenColor();
#endif
}
if (lastsp && global) {
/* perform global rearrangements */
if (progress) {
printf("Doing global rearrangements\n");
printf(" !");
for (j = 1; j <= nonodes; j++)
if ( j % (( nonodes / 72 ) + 1 ) == 0 )
putchar('-');
printf("!\n");
}
global2 = false;
do {
succeded = false;
if (progress)
printf(" ");
/* FIXME: tymes gets clobbered by tryadd() */
/* save_tymes(&curtree, tymes); */
for (j = 0; j < nonodes; j++) {
oldbest = bestree.likelihood;
bestyet = UNDEFINED;
item = curtree.nodep[j];
if (item != curtree.root) {
nufork = pnode(&curtree, item->back); /* parent fork */
if (nufork != curtree.root) {
tmp = nufork->next->back;
if (tmp == item)
tmp = nufork->next->next->back;
/* can't figure out why we never get here */
}
else {
if (nufork->next->back != item)
tmp = nufork->next->back;
else tmp = nufork->next->next->back;
} /* if we add item at tmp we have done nothing */
assert( all_tymes_valid(curtree.root, 0.98*MIN_BRANCH_LENGTH, false) );
dnamlk_re_move(&item, &nufork, false);
/* there = curtree.root; */
there = tmp;
addpreorder(curtree.root, item, nufork, true, true);
if ( tmp != there && bestree.likelihood > oldbest)
succeded = true;
dnamlk_add(there, item, nufork);
if (global2)
restore_tymes(&curtree,tymes);
}
if (progress) {
if ( j % (( nonodes / 72 ) + 1 ) == 0 )
putchar('.');
fflush(stdout);
}
}
if (progress)
putchar('\n');
} while ( succeded );
}
}
if (njumble > 1 && lastsp) {
for (i = 0; i < spp; i++ )
dnamlk_re_move(&curtree.nodep[i], &dummy, false);
if (jumb == 1 || bestree2.likelihood < bestree.likelihood)
copy_(&bestree, &bestree2, nonodes, rcategs);
}
if (jumb == njumble) {
if (njumble > 1)
copy_(&bestree2, &curtree, nonodes, rcategs);
else copy_(&bestree, &curtree, nonodes, rcategs);
fprintf(outfile, "\n\n");
treevaluate();
curtree.likelihood = dnamlk_evaluate(curtree.root);
if (treeprint)
mlk_printree(outfile, &curtree);
summarize(outfile);
if (trout) {
col = 0;
dnamlk_treeout(curtree.root);
}
}
} else { /* if ( usertree ) */
/* Open in binary: ftell() is broken for UNIX line-endings under WIN32 */
treestr = ajStrGetuniquePtr(&phylotrees[0]->Tree);
inittable_for_usertree (treestr);
if(numtrees > MAXSHIMOTREES)
shimotrees = MAXSHIMOTREES;
else
shimotrees = numtrees;
if (numtrees > 2)
emboss_initseed(inseed, &inseed0, seed);
l0gl = (double *)Malloc(shimotrees * sizeof(double));
l0gf = (double **)Malloc(shimotrees * sizeof(double *));
for (i=0; i < shimotrees; ++i)
l0gf[i] = (double *)Malloc(endsite * sizeof(double));
if (treeprint) {
fprintf(outfile, "User-defined tree");
if (numtrees > 1)
putc('s', outfile);
fprintf(outfile, ":\n\n");
}
fprintf(outfile, "\n\n");
which = 1;
max_nonodes = nonodes;
while (which <= numtrees) {
/* These initializations required each time through the loop
since multiple trees require re-initialization */
dummy_haslengths = true;
nextnode = 0;
dummy_first = true;
goteof = false;
lngths = lengthsopt;
nonodes = max_nonodes;
treestr = ajStrGetuniquePtr(&phylotrees[which-1]->Tree);
treeread(&treestr, &root, dummy_treenode, &goteof, &dummy_first,
curtree.nodep, &nextnode, &dummy_haslengths, &grbg,
initdnamlnode, false, nonodes);
if (goteof && (which <= numtrees)) {
/* if we hit the end of the file prematurely */
printf ("\n");
printf ("ERROR: trees missing at end of file.\n");
printf ("\tExpected number of trees:\t\t%ld\n", numtrees);
printf ("\tNumber of trees actually in file:\t%ld.\n\n", which - 1);
exxit(-1);
}
nonodes = nextnode;
root = curtree.nodep[root->index - 1];
curtree.root = root;
if (lngths)
tymetrav(curtree.root);
else
init_tymes(curtree.root, initialv);
treevaluate();
if (treeprint)
mlk_printree(outfile, &curtree);
summarize(outfile);
if (trout) {
col = 0;
dnamlk_treeout(curtree.root);
}
if(which < numtrees){
freex_notip(nonodes, curtree.nodep);
gdispose(curtree.root, &grbg, curtree.nodep);
}
which++;
}
FClose(intree);
if (!auto_ && numtrees > 1 && weightsum > 1 )
standev2(numtrees, maxwhich, 0, endsite, maxlogl, l0gl, l0gf,
aliasweight, seed);
}
if (jumb == njumble) {
if (progress) {
printf("\nOutput written to file \"%s\"\n", outfilename);
if (trout)
printf("\nTree also written onto file \"%s\"\n", outtreename);
}
free(contribution);
freex(nonodes, curtree.nodep);
if (!usertree) {
freex(nonodes, bestree.nodep);
if (njumble > 1)
freex(nonodes, bestree2.nodep);
}
}
free(root);
freetable();
} /* maketree */
/*?? Dnaml has a clean-up function for freeing memory, closing files, etc.
Put one here too? */
int main(int argc, Char *argv[])
{ /* DNA Maximum Likelihood with molecular clock */
/* Initialize mlclock.c */
mlclock_init(&curtree, &dnamlk_evaluate);
#ifdef MAC
argc = 1; /* macsetup("Dnamlk", "Dnamlk"); */
argv[0] = "Dnamlk";
#endif
init(argc,argv);
emboss_getoptions("fdnamlk", argc, argv);
progname = argv[0];
ibmpc = IBMCRT;
ansi = ANSICRT;
firstset = true;
doinit();
ttratio0 = ttratio;
/* Data set loop */
for (ith = 1; ith <= datasets; ith++) {
ttratio = ttratio0;
if (datasets > 1) {
fprintf(outfile, "Data set # %ld:\n\n", ith);
if (progress)
printf("\nData set # %ld:\n", ith);
}
getinput();
if (ith == 1)
firstset = false;
/* Jumble loop */
if (usertree)
maketree();
else
for (jumb = 1; jumb <= njumble; jumb++)
maketree();
}
/* Close files */
FClose(infile);
FClose(outfile);
FClose(outtree);
#ifdef MAC
fixmacfile(outfilename);
fixmacfile(outtreename);
#endif
printf("\nDone.\n\n");
#ifdef WIN32
phyRestoreConsoleAttributes();
#endif
embExit();
return 0;
} /* DNA Maximum Likelihood with molecular clock */
PHYLIPNEW-3.69.650/src/dnadist.c 0000664 0001750 0001750 00000075376 11616234203 012667 0000000 0000000 #include "phylip.h"
#include "seq.h"
/* version 3.6. (c) Copyright 1993-2004 by the University of Washington.
Written by Joseph Felsenstein, Akiko Fuseki, Sean Lamont, and Andrew Keeffe.
Permission is granted to copy and use this program provided no fee is
charged for it and provided that this copyright notice is not removed. */
#define iterationsd 100 /* number of iterates of EM for each distance */
typedef struct valrec {
double rat, ratxv, z1, y1, z1zz, z1yy, z1xv;
} valrec;
AjPSeqset* seqsets = NULL;
AjPPhyloProp phyloratecat = NULL;
AjPPhyloProp phyloweights = NULL;
ajint numseqs;
ajint numwts;
extern sequence y;
Char infilename[FNMLNGTH], catfilename[FNMLNGTH], weightfilename[FNMLNGTH];
const char* outfilename;
AjPFile embossoutfile;
long sites, categs, weightsum, datasets, ith, rcategs;
boolean freqsfrom, jukes, kimura, logdet, gama, invar, similarity, lower, f84,
weights, progress, ctgry, mulsets, justwts, firstset, baddists, human;
boolean matrix_flags; /* Matrix output format */
node **nodep;
double xi, xv, ttratio, ttratio0, freqa, freqc, freqg, freqt, freqr, freqy,
freqar, freqcy, freqgr, freqty, cvi, invarfrac, sumrates, fracchange;
steptr oldweight;
double rate[maxcategs];
double **d;
double sumweightrat; /* these values were propagated */
double *weightrat; /* to global values from */
valrec tbl[maxcategs]; /* function makedists. */
#ifndef OLDC
/* function prototypes */
//void getoptions(void);
void emboss_getoptions(char *pgm, int argc, char *argv[]);
void allocrest(void);
void reallocsites(void);
void doinit(void);
void printcategories(void);
void inputoptions(void);
void dnadist_sitesort(void);
void dnadist_sitecombine(void);
void dnadist_sitescrunch(void);
void makeweights(void);
void dnadist_makevalues(void);
void dnadist_empiricalfreqs(void);
void getinput(void);
void inittable(void);
double lndet(double (*a)[4]);
void makev(long, long, double *);
void makedists(void);
void writedists(void);
/* function prototypes */
#endif
void emboss_getoptions(char *pgm, int argc, char *argv[])
{
AjPStr method = NULL;
AjPStr gammamethod = NULL;
AjPFloat basefreq;
AjPFloat arrayval;
/*boolean ttr;*/
ctgry = false;
categs = 1;
cvi = 1.0;
rcategs = 1;
rate[0] = 1.0;
freqsfrom = true;
gama = false;
invar = false;
invarfrac = 0.0;
jukes = false;
justwts = false;
kimura = false;
logdet = false;
f84 = false;
lower = false;
human = false;
similarity = false;
ttratio = 2.0;
/*ttr = false;*/
weights = false;
printdata = false;
progress = true;
mulsets = false;
datasets = 1;
matrix_flags = MAT_MACHINE;
embInitPV(pgm, argc, argv, "PHYLIPNEW",VERSION);
seqsets = ajAcdGetSeqsetall("sequence");
numseqs = 0;
while (seqsets[numseqs])
numseqs++;
phyloweights = ajAcdGetProperties("weights");
if (phyloweights)
{
weights = true;
numwts = ajPhyloPropGetSize(phyloweights);
}
if (numseqs > 1) {
mulsets = true;
datasets = numseqs;
}
else if (numwts > 1) {
mulsets = true;
datasets = numwts;
justwts = true;
}
method = ajAcdGetListSingle("method");
if(ajStrMatchC(method, "f")) {
f84 = true;
ttratio = ajAcdGetFloat("ttratio");
freqsfrom = ajAcdGetToggle("freqsfrom");
}
else if(ajStrMatchC(method, "k")) {
kimura = true;
ttratio = ajAcdGetFloat("ttratio");
}
else if(ajStrMatchC(method, "j")) jukes = true;
else if(ajStrMatchC(method, "l")) logdet = true;
else if(ajStrMatchC(method, "s")) similarity = true;
if( (f84) || (kimura) || (jukes) ) {
gammamethod = ajAcdGetListSingle("gammatype");
if(ajStrMatchC(gammamethod, "g")) {
gama = true;
cvi = ajAcdGetFloat("gammacoefficient");
cvi = 1.0 / (cvi * cvi);
}
else if(ajStrMatchC(gammamethod, "i")) {
invar = true;
cvi = ajAcdGetFloat("gammacoefficient");
cvi = 1.0 / (cvi * cvi);
invarfrac = ajAcdGetFloat("invarfrac");
}
else if(ajStrMatchC(gammamethod, "n")) {
categs = ajAcdGetInt("ncategories");
}
}
if (categs > 1) {
ctgry = true;
arrayval = ajAcdGetArray("rate");
emboss_initcategs(arrayval, categs, rate);
}
printdata = ajAcdGetBoolean("printdata");
progress = ajAcdGetBoolean("progress");
lower = ajAcdGetBoolean("lower");
if(lower)
matrix_flags = MAT_LOWER;
human = ajAcdGetBoolean("humanreadable");
if(human)
matrix_flags |= MAT_HUMAN;
if(!freqsfrom) {
basefreq = ajAcdGetArray("basefreq");
freqa = ajFloatGet(basefreq, 0);
freqc = ajFloatGet(basefreq, 1);
freqg = ajFloatGet(basefreq, 2);
freqt = ajFloatGet(basefreq, 3);
}
embossoutfile = ajAcdGetOutfile("outfile");
emboss_openfile(embossoutfile, &outfile, &outfilename);
/* fprintf(outfile, "\nNucleic acid sequence Distance Matrix program,");*/
/* fprintf(outfile, " version %s\n\n",VERSION);*/
} /* emboss_getoptions */
void allocrest(void)
{
long i;
y = (Char **)Malloc(spp*sizeof(Char *));
nodep = (node **)Malloc(spp*sizeof(node *));
for (i = 0; i < spp; i++) {
y[i] = (Char *)Malloc(sites*sizeof(Char));
nodep[i] = (node *)Malloc(sizeof(node));
}
d = (double **)Malloc(spp*sizeof(double *));
for (i = 0; i < spp; i++)
d[i] = (double*)Malloc(spp*sizeof(double));
nayme = (naym *)Malloc(spp*sizeof(naym));
category = (steptr)Malloc(sites*sizeof(long));
oldweight = (steptr)Malloc(sites*sizeof(long));
weight = (steptr)Malloc(sites*sizeof(long));
alias = (steptr)Malloc(sites*sizeof(long));
ally = (steptr)Malloc(sites*sizeof(long));
location = (steptr)Malloc(sites*sizeof(long));
weightrat = (double *)Malloc(sites*sizeof(double));
} /* allocrest */
void reallocsites(void)
{/* The amount of sites can change between runs
this function reallocates all the variables
whose size depends on the amount of sites */
long i;
for (i = 0; i < spp; i++) {
free(y[i]);
y[i] = (Char *)Malloc(sites*sizeof(Char));
}
free(category);
free(oldweight);
free(weight);
free(alias);
free(ally);
free(location);
free(weightrat);
category = (steptr)Malloc(sites*sizeof(long));
oldweight = (steptr)Malloc(sites*sizeof(long));
weight = (steptr)Malloc(sites*sizeof(long));
alias = (steptr)Malloc(sites*sizeof(long));
ally = (steptr)Malloc(sites*sizeof(long));
location = (steptr)Malloc(sites*sizeof(long));
weightrat = (double *)Malloc(sites*sizeof(double));
} /* reallocsites */
void doinit(void)
{
/* initializes variables */
inputnumbersseq(seqsets[0], &spp, &sites, &nonodes, 1);
if (printdata)
fprintf(outfile, "%2ld species, %3ld sites\n", spp, sites);
allocrest();
} /* doinit */
void printcategories(void)
{ /* print out list of categories of sites */
long i, j;
fprintf(outfile, "Rate categories\n\n");
for (i = 1; i <= nmlngth + 3; i++)
putc(' ', outfile);
for (i = 1; i <= sites; i++) {
fprintf(outfile, "%ld", category[i - 1]);
if (i % 60 == 0) {
putc('\n', outfile);
for (j = 1; j <= nmlngth + 3; j++)
putc(' ', outfile);
} else if (i % 10 == 0)
putc(' ', outfile);
}
fprintf(outfile, "\n\n");
} /* printcategories */
void inputoptions(void)
{
/* read options information */
long i;
if (!firstset && !justwts) {
samenumspseq(seqsets[ith-1], &sites, ith);
reallocsites();
}
for (i = 0; i < sites; i++) {
category[i] = 1;
oldweight[i] = 1;
}
if (justwts || weights)
inputweightsstr(phyloweights->Str[ith-1], sites, oldweight, &weights);
if (printdata)
putc('\n', outfile);
if (jukes && printdata)
fprintf(outfile, " Jukes-Cantor Distance\n");
if (kimura && printdata)
fprintf(outfile, " Kimura 2-parameter Distance\n");
if (f84 && printdata)
fprintf(outfile, " F84 Distance\n");
if (similarity)
fprintf(outfile, " \n Table of similarity between sequences\n");
if (firstset && printdata && (kimura || f84))
fprintf(outfile, "\nTransition/transversion ratio = %10.6f\n", ttratio);
if (ctgry && categs > 1) {
inputcategsstr(phyloratecat->Str[0], 0, sites, category, categs, "DnaDist");
if (printdata)
printcategs(outfile, sites, category, "Site categories");
} else if (printdata && (categs > 1)) {
fprintf(outfile, "\nSite category Rate of change\n\n");
for (i = 1; i <= categs; i++)
fprintf(outfile, "%12ld%13.3f\n", i, rate[i - 1]);
putc('\n', outfile);
printcategories();
}
if (jukes)
ttratio = 0.5000001;
if (weights && printdata)
printweights(outfile, 0, sites, oldweight, "Sites");
} /* inputoptions */
void dnadist_sitesort(void)
{
/* Shell sort of sites lexicographically */
long gap, i, j, jj, jg, k, itemp;
boolean flip, tied;
gap = sites / 2;
while (gap > 0) {
for (i = gap + 1; i <= sites; i++) {
j = i - gap;
flip = true;
while (j > 0 && flip) {
jj = alias[j - 1];
jg = alias[j + gap - 1];
tied = (oldweight[jj - 1] == oldweight[jg - 1]);
flip = (oldweight[jj - 1] < oldweight[jg - 1] ||
(tied && category[jj - 1] > category[jg - 1]));
tied = (tied && category[jj - 1] == category[jg - 1]);
k = 1;
while (k <= spp && tied) {
flip = (y[k - 1][jj - 1] > y[k - 1][jg - 1]);
tied = (tied && y[k - 1][jj - 1] == y[k - 1][jg - 1]);
k++;
}
if (!flip)
break;
itemp = alias[j - 1];
alias[j - 1] = alias[j + gap - 1];
alias[j + gap - 1] = itemp;
j -= gap;
}
}
gap /= 2;
}
} /* dnadist_sitesort */
void dnadist_sitecombine(void)
{
/* combine sites that have identical patterns */
long i, j, k;
boolean tied;
i = 1;
while (i < sites) {
j = i + 1;
tied = true;
while (j <= sites && tied) {
tied = (oldweight[alias[i - 1] - 1] == oldweight[alias[j - 1] - 1] &&
category[alias[i - 1] - 1] == category[alias[j - 1] - 1]);
k = 1;
while (k <= spp && tied) {
tied = (tied &&
y[k - 1][alias[i - 1] - 1] == y[k - 1][alias[j - 1] - 1]);
k++;
}
if (!tied)
break;
ally[alias[j - 1] - 1] = alias[i - 1];
j++;
}
i = j;
}
} /* dnadist_sitecombine */
void dnadist_sitescrunch(void)
{
/* move so one representative of each pattern of
sites comes first */
long i, j, itemp;
boolean done, found, completed;
done = false;
i = 1;
j = 2;
while (!done) {
if (ally[alias[i - 1] - 1] != alias[i - 1]) {
if (j <= i)
j = i + 1;
if (j <= sites) {
do {
found = (ally[alias[j - 1] - 1] == alias[j - 1]);
j++;
completed = (j > sites);
if (j <= sites)
completed = (oldweight[alias[j - 1] - 1] == 0);
} while (!(found || completed));
if (found) {
j--;
itemp = alias[i - 1];
alias[i - 1] = alias[j - 1];
alias[j - 1] = itemp;
} else
done = true;
} else
done = true;
}
i++;
done = (done || i >= sites);
}
} /* dnadist_sitescrunch */
void makeweights(void)
{
/* make up weights vector to avoid duplicate computations */
long i;
for (i = 1; i <= sites; i++) {
alias[i - 1] = i;
ally[i - 1] = i;
weight[i - 1] = 0;
}
dnadist_sitesort();
dnadist_sitecombine();
dnadist_sitescrunch();
endsite = 0;
for (i = 1; i <= sites; i++) {
if (ally[i - 1] == i && oldweight[i - 1] > 0)
endsite++;
}
for (i = 1; i <= endsite; i++)
location[alias[i - 1] - 1] = i;
weightsum = 0;
for (i = 0; i < sites; i++)
weightsum += oldweight[i];
sumrates = 0.0;
for (i = 0; i < sites; i++)
sumrates += oldweight[i] * rate[category[i] - 1];
for (i = 0; i < categs; i++)
rate[i] *= weightsum / sumrates;
for (i = 0; i < sites; i++)
weight[location[ally[i] - 1] - 1] += oldweight[i];
} /* makeweights */
void dnadist_makevalues(void)
{
/* set up fractional likelihoods at tips */
long i, j, k;
bases b;
for (i = 0; i < spp; i++) {
nodep[i]->x = (phenotype)Malloc(endsite*sizeof(ratelike));
for (j = 0; j < endsite; j++)
nodep[i]->x[j] = (ratelike)Malloc(rcategs*sizeof(sitelike));
}
for (k = 0; k < endsite; k++) {
j = alias[k];
for (i = 0; i < spp; i++) {
for (b = A; (long)b <= (long)T; b = (bases)((long)b + 1))
nodep[i]->x[k][0][(long)b - (long)A] = 0.0;
switch (y[i][j - 1]) {
case 'A':
nodep[i]->x[k][0][0] = 1.0;
break;
case 'C':
nodep[i]->x[k][0][(long)C - (long)A] = 1.0;
break;
case 'G':
nodep[i]->x[k][0][(long)G - (long)A] = 1.0;
break;
case 'T':
nodep[i]->x[k][0][(long)T - (long)A] = 1.0;
break;
case 'U':
nodep[i]->x[k][0][(long)T - (long)A] = 1.0;
break;
case 'M':
nodep[i]->x[k][0][0] = 1.0;
nodep[i]->x[k][0][(long)C - (long)A] = 1.0;
break;
case 'R':
nodep[i]->x[k][0][0] = 1.0;
nodep[i]->x[k][0][(long)G - (long)A] = 1.0;
break;
case 'W':
nodep[i]->x[k][0][0] = 1.0;
nodep[i]->x[k][0][(long)T - (long)A] = 1.0;
break;
case 'S':
nodep[i]->x[k][0][(long)C - (long)A] = 1.0;
nodep[i]->x[k][0][(long)G - (long)A] = 1.0;
break;
case 'Y':
nodep[i]->x[k][0][(long)C - (long)A] = 1.0;
nodep[i]->x[k][0][(long)T - (long)A] = 1.0;
break;
case 'K':
nodep[i]->x[k][0][(long)G - (long)A] = 1.0;
nodep[i]->x[k][0][(long)T - (long)A] = 1.0;
break;
case 'B':
nodep[i]->x[k][0][(long)C - (long)A] = 1.0;
nodep[i]->x[k][0][(long)G - (long)A] = 1.0;
nodep[i]->x[k][0][(long)T - (long)A] = 1.0;
break;
case 'D':
nodep[i]->x[k][0][0] = 1.0;
nodep[i]->x[k][0][(long)G - (long)A] = 1.0;
nodep[i]->x[k][0][(long)T - (long)A] = 1.0;
break;
case 'H':
nodep[i]->x[k][0][0] = 1.0;
nodep[i]->x[k][0][(long)C - (long)A] = 1.0;
nodep[i]->x[k][0][(long)T - (long)A] = 1.0;
break;
case 'V':
nodep[i]->x[k][0][0] = 1.0;
nodep[i]->x[k][0][(long)C - (long)A] = 1.0;
nodep[i]->x[k][0][(long)G - (long)A] = 1.0;
break;
case 'N':
for (b = A; (long)b <= (long)T; b = (bases)((long)b + 1))
nodep[i]->x[k][0][(long)b - (long)A] = 1.0;
break;
case 'X':
for (b = A; (long)b <= (long)T; b = (bases)((long)b + 1))
nodep[i]->x[k][0][(long)b - (long)A] = 1.0;
break;
case '?':
for (b = A; (long)b <= (long)T; b = (bases)((long)b + 1))
nodep[i]->x[k][0][(long)b - (long)A] = 1.0;
break;
case 'O':
for (b = A; (long)b <= (long)T; b = (bases)((long)b + 1))
nodep[i]->x[k][0][(long)b - (long)A] = 1.0;
break;
case '-':
for (b = A; (long)b <= (long)T; b = (bases)((long)b + 1))
nodep[i]->x[k][0][(long)b - (long)A] = 1.0;
break;
}
}
}
} /* dnadist_makevalues */
void dnadist_empiricalfreqs(void)
{
/* Get empirical base frequencies from the data */
long i, j, k;
double sum, suma, sumc, sumg, sumt, w;
freqa = 0.25;
freqc = 0.25;
freqg = 0.25;
freqt = 0.25;
for (k = 1; k <= 8; k++) {
suma = 0.0;
sumc = 0.0;
sumg = 0.0;
sumt = 0.0;
for (i = 0; i < spp; i++) {
for (j = 0; j < endsite; j++) {
w = weight[j];
sum = freqa * nodep[i]->x[j][0][0];
sum += freqc * nodep[i]->x[j][0][(long)C - (long)A];
sum += freqg * nodep[i]->x[j][0][(long)G - (long)A];
sum += freqt * nodep[i]->x[j][0][(long)T - (long)A];
suma += w * freqa * nodep[i]->x[j][0][0] / sum;
sumc += w * freqc * nodep[i]->x[j][0][(long)C - (long)A] / sum;
sumg += w * freqg * nodep[i]->x[j][0][(long)G - (long)A] / sum;
sumt += w * freqt * nodep[i]->x[j][0][(long)T - (long)A] / sum;
}
}
sum = suma + sumc + sumg + sumt;
freqa = suma / sum;
freqc = sumc / sum;
freqg = sumg / sum;
freqt = sumt / sum;
}
} /* dnadist_empiricalfreqs */
void getinput(void)
{
/* reads the input data */
inputoptions();
if ((!freqsfrom) && !logdet && !similarity) {
if (kimura || jukes) {
freqa = 0.25;
freqc = 0.25;
freqg = 0.25;
freqt = 0.25;
}
getbasefreqs(freqa, freqc, freqg, freqt, &freqr, &freqy, &freqar, &freqcy,
&freqgr, &freqty, &ttratio, &xi, &xv, &fracchange,
freqsfrom, printdata);
if (freqa < 0.00000001) {
freqa = 0.000001;
freqc = 0.999999*freqc;
freqg = 0.999999*freqg;
freqt = 0.999999*freqt;
}
if (freqc < 0.00000001) {
freqa = 0.999999*freqa;
freqc = 0.000001;
freqg = 0.999999*freqg;
freqt = 0.999999*freqt;
}
if (freqg < 0.00000001) {
freqa = 0.999999*freqa;
freqc = 0.999999*freqc;
freqg = 0.000001;
freqt = 0.999999*freqt;
}
if (freqt < 0.00000001) {
freqa = 0.999999*freqa;
freqc = 0.999999*freqc;
freqg = 0.999999*freqg;
freqt = 0.000001;
}
}
if (!justwts || firstset)
seq_inputdata(seqsets[ith-1],sites);
makeweights();
dnadist_makevalues();
if (freqsfrom) {
dnadist_empiricalfreqs();
getbasefreqs(freqa, freqc, freqg, freqt, &freqr, &freqy, &freqar, &freqcy,
&freqgr, &freqty, &ttratio, &xi, &xv, &fracchange,
freqsfrom, printdata);
}
} /* getinput */
void inittable(void)
{
/* Define a lookup table. Precompute values and store in a table */
long i;
for (i = 0; i < categs; i++) {
tbl[i].rat = rate[i];
tbl[i].ratxv = rate[i] * xv;
}
} /* inittable */
double lndet(double (*a)[4])
{
long i, j, k;
double temp, ld;
/*Gauss-Jordan reduction -- invert matrix a in place,
overwriting previous contents of a. On exit, matrix a
contains the inverse, lndet contains the log of the determinant */
ld = 1.0;
for (i = 0; i < 4; i++) {
ld *= a[i][i];
temp = 1.0 / a[i][i];
a[i][i] = 1.0;
for (j = 0; j < 4; j++)
a[i][j] *= temp;
for (j = 0; j < 4; j++) {
if (j != i) {
temp = a[j][i];
a[j][i] = 0.0;
for (k = 0; k < 4; k++)
a[j][k] -= temp * a[i][k];
}
}
}
if (ld <= 0.0)
return(99.0);
else
return(log(ld));
} /* lndet */
void makev(long m, long n, double *v)
{
/* compute one distance */
long i, j, k, l, it, num1, num2, idx;
long numerator = 0, denominator = 0;
double sum, sum1, sum2, sumyr, lz, aa, bb, cc, vv=0,
p1, p2, p3, q1, q2, q3, tt, delta=0.0, slope,
xx1freqa, xx1freqc, xx1freqg, xx1freqt;
double *prod, *prod2, *prod3;
boolean quick, jukesquick, kimquick, logdetquick, overlap;
bases b;
node *p, *q;
sitelike xx1, xx2;
double basetable[4][4]; /* for quick logdet */
double basefreq1[4], basefreq2[4];
p = nodep[m - 1];
q = nodep[n - 1];
/* check for overlap between sequences */
overlap = false;
for(i=0 ; i < sites ; i++){
if((strchr("NX?O-",y[m-1][i])==NULL) &&
(strchr("NX?O-",y[n-1][i])==NULL)){
overlap = true;
break;
}
}
if(!overlap){
printf("\nWARNING: NO OVERLAP BETWEEN SEQUENCES %ld AND %ld; -1.0 WAS WRITTEN\n", m, n);
baddists = true;
return;
}
quick = (!ctgry || categs == 1);
if (jukes || kimura || logdet || similarity) {
numerator = 0;
denominator = 0;
for (i = 0; i < endsite; i++) {
memcpy(xx1, p->x[i][0], sizeof(sitelike));
memcpy(xx2, q->x[i][0], sizeof(sitelike));
sum = 0.0;
sum1 = 0.0;
sum2 = 0.0;
for (b = A; (long)b <= (long)T; b = (bases)((long)b + 1)) {
sum1 += xx1[(long)b - (long)A];
sum2 += xx2[(long)b - (long)A];
sum += xx1[(long)b - (long)A] * xx2[(long)b - (long)A];
}
quick = (quick && (sum1 == 1.0 || sum1 == 4.0) &&
(sum2 == 1.0 || sum2 == 4.0));
if (sum1 == 1.0 && sum2 == 1.0) {
numerator += (long)(weight[i] * sum);
denominator += weight[i];
}
}
}
jukesquick = ((jukes || similarity) && quick);
kimquick = (kimura && quick);
logdetquick = (logdet && quick);
if (logdet && !quick) {
printf(" WARNING: CANNOT CALCULATE LOGDET DISTANCE\n");
printf(" WITH PRESENT PROGRAM IF PARTIALLY AMBIGUOUS NUCLEOTIDES\n");
printf(" -1.0 WAS WRITTEN\n");
baddists = true;
}
if (jukesquick && jukes && (numerator * 4 <= denominator)) {
printf("\nWARNING: INFINITE DISTANCE BETWEEN ");
printf(" SPECIES %3ld AND %3ld\n", m, n);
printf(" -1.0 WAS WRITTEN\n");
baddists = true;
}
if (jukesquick && invar
&& (4 * (((double)numerator / denominator) - invarfrac)
<= (1.0 - invarfrac))) {
printf("\nWARNING: DIFFERENCE BETWEEN SPECIES %3ld AND %3ld", m, n);
printf(" TOO LARGE FOR INVARIABLE SITES\n");
printf(" -1.0 WAS WRITTEN\n");
baddists = true;
}
if (jukesquick) {
if (!gama && !invar)
vv = -0.75 * log((4.0*((double)numerator / denominator) - 1.0) / 3.0);
else if (!invar)
vv = 0.75 * cvi * (exp(-(1/cvi)*
log((4.0 * ((double)numerator / denominator) - 1.0) / 3.0)) - 1.0);
else
vv = 0.75 * cvi * (exp(-(1/cvi)*
log((4.0 * ((double)numerator / denominator - invarfrac)/
(1.0-invarfrac) - 1.0) / 3.0)) - 1.0);
}
if (kimquick) {
num1 = 0;
num2 = 0;
denominator = 0;
for (i = 0; i < endsite; i++) {
memcpy(xx1, p->x[i][0], sizeof(sitelike));
memcpy(xx2, q->x[i][0], sizeof(sitelike));
sum = 0.0;
sum1 = 0.0;
sum2 = 0.0;
for (b = A; (long)b <= (long)T; b = (bases)((long)b + 1)) {
sum1 += xx1[(long)b - (long)A];
sum2 += xx2[(long)b - (long)A];
sum += xx1[(long)b - (long)A] * xx2[(long)b - (long)A];
}
sumyr = (xx1[0] + xx1[(long)G - (long)A])
* (xx2[0] + xx2[(long)G - (long)A]) +
(xx1[(long)C - (long)A] + xx1[(long)T - (long)A]) *
(xx2[(long)C - (long)A] + xx2[(long)T - (long)A]);
if (sum1 == 1.0 && sum2 == 1.0) {
num1 += (long)(weight[i] * sum);
num2 += (long)(weight[i] * (sumyr - sum));
denominator += weight[i];
}
}
tt = ((1.0 - (double)num1 / denominator)-invarfrac)/(1.0-invarfrac);
if (tt > 0.0) {
delta = 0.1;
tt = delta;
it = 0;
while (fabs(delta) > 0.0000002 && it < iterationsd) {
it++;
if (!gama) {
p1 = exp(-tt);
p2 = exp(-xv * tt) - exp(-tt);
p3 = 1.0 - exp(-xv * tt);
} else {
p1 = exp(-cvi * log(1 + tt / cvi));
p2 = exp(-cvi * log(1 + xv * tt / cvi))
- exp(-cvi * log(1 + tt / cvi));
p3 = 1.0 - exp(-cvi * log(1 + xv * tt / cvi));
}
q1 = p1 + p2 / 2.0 + p3 / 4.0;
q2 = p2 / 2.0 + p3 / 4.0;
q3 = p3 / 2.0;
q1 = q1 * (1.0-invarfrac) + invarfrac;
q2 *= (1.0 - invarfrac);
q3 *= (1.0 - invarfrac);
if (!gama && !invar)
slope = 0.5 * exp(-tt) * (num2 / q2 - num1 / q1) +
0.25 * xv * exp(-xv * tt) *
((denominator - num1 - num2) * 2 / q3 - num2 / q2 - num1 / q1);
else
slope = 0.5 * (1 / (1 + tt / cvi)) * exp(-cvi * log(1 + tt / cvi)) *
(num2 / q2 - num1 / q1) + 0.25 * (xv / (1 + xv * tt / cvi)) *
exp(-cvi * log(1 + xv * tt / cvi)) *
((denominator - num1 - num2) * 2 / q3 - num2 / q2 - num1 / q1);
slope *= (1.0-invarfrac);
if (slope < 0.0)
delta = fabs(delta) / -2.0;
else
delta = fabs(delta);
tt += delta;
}
}
if ((delta >= 0.1) && (!similarity)) {
printf("\nWARNING: DIFFERENCE BETWEEN SPECIES %3ld AND %3ld", m, n);
if (invar)
printf(" TOO LARGE FOR INVARIABLE SITES\n");
else
printf(" TOO LARGE TO ESTIMATE DISTANCE\n");
printf(" -1.0 WAS WRITTEN\n");
baddists = true;
}
vv = fracchange * tt;
}
if (!(jukesquick || kimquick || logdet)) {
prod = (double *)Malloc(sites*sizeof(double));
prod2 = (double *)Malloc(sites*sizeof(double));
prod3 = (double *)Malloc(sites*sizeof(double));
for (i = 0; i < endsite; i++) {
memcpy(xx1, p->x[i][0], sizeof(sitelike));
memcpy(xx2, q->x[i][0], sizeof(sitelike));
xx1freqa = xx1[0] * freqa;
xx1freqc = xx1[(long)C - (long)A] * freqc;
xx1freqg = xx1[(long)G - (long)A] * freqg;
xx1freqt = xx1[(long)T - (long)A] * freqt;
sum1 = xx1freqa + xx1freqc + xx1freqg + xx1freqt;
sum2 = freqa * xx2[0] + freqc * xx2[(long)C - (long)A] +
freqg * xx2[(long)G - (long)A] + freqt * xx2[(long)T - (long)A];
prod[i] = sum1 * sum2;
prod2[i] = (xx1freqa + xx1freqg) *
(xx2[0] * freqar + xx2[(long)G - (long)A] * freqgr) +
(xx1freqc + xx1freqt) *
(xx2[(long)C - (long)A] * freqcy + xx2[(long)T - (long)A] * freqty);
prod3[i] = xx1freqa * xx2[0] + xx1freqc * xx2[(long)C - (long)A] +
xx1freqg * xx2[(long)G - (long)A] + xx1freqt * xx2[(long)T - (long)A];
}
tt = 0.1;
delta = 0.1;
it = 1;
while (it < iterationsd && fabs(delta) > 0.0000002) {
slope = 0.0;
if (tt > 0.0) {
lz = -tt;
for (i = 0; i < categs; i++) {
if (!gama) {
tbl[i].z1 = exp(tbl[i].ratxv * lz);
tbl[i].z1zz = exp(tbl[i].rat * lz);
}
else {
tbl[i].z1 = exp(-cvi*log(1.0-tbl[i].ratxv * lz/cvi));
tbl[i].z1zz = exp(-cvi*log(1.0-tbl[i].rat * lz/cvi));
}
tbl[i].y1 = 1.0 - tbl[i].z1;
tbl[i].z1yy = tbl[i].z1 - tbl[i].z1zz;
tbl[i].z1xv = tbl[i].z1 * xv;
}
for (i = 0; i < endsite; i++) {
idx = category[alias[i] - 1];
cc = prod[i];
bb = prod2[i];
aa = prod3[i];
if (!gama && !invar)
slope += weightrat[i] * (tbl[idx - 1].z1zz * (bb - aa) +
tbl[idx - 1].z1xv * (cc - bb)) /
(aa * tbl[idx - 1].z1zz + bb * tbl[idx - 1].z1yy +
cc * tbl[idx - 1].y1);
else
slope += (1.0-invarfrac) * weightrat[i] * (
((tbl[idx-1].rat)/(1.0-tbl[idx-1].rat * lz/cvi))
* tbl[idx - 1].z1zz * (bb - aa) +
((tbl[idx-1].ratxv)/(1.0-tbl[idx-1].ratxv * lz/cvi))
* tbl[idx - 1].z1 * (cc - bb)) /
(aa * ((1.0-invarfrac)*tbl[idx - 1].z1zz + invarfrac)
+ bb * (1.0-invarfrac)*tbl[idx - 1].z1yy
+ cc * (1.0-invarfrac)*tbl[idx - 1].y1);
}
}
if (slope < 0.0)
delta = fabs(delta) / -2.0;
else
delta = fabs(delta);
tt += delta;
it++;
}
if ((delta >= 0.1) && (!similarity)) {
printf("\nWARNING: DIFFERENCE BETWEEN SPECIES %3ld AND %3ld", m, n);
if (invar)
printf(" TOO LARGE FOR INVARIABLE SITES\n");
else
printf(" TOO LARGE TO ESTIMATE DISTANCE\n");
printf(" -1.0 WAS WRITTEN\n");
baddists = true;
}
vv = tt * fracchange;
free(prod);
free(prod2);
free(prod3);
}
if (logdetquick) { /* compute logdet when no ambiguous nucleotides */
for (i = 0; i < 4; i++) {
basefreq1[i] = 0.0;
basefreq2[i] = 0.0;
for (j = 0; j < 4; j++)
basetable[i][j] = 0.0;
}
for (i = 0; i < endsite; i++) {
k = 0;
while (p->x[i][0][k] == 0.0)
k++;
basefreq1[k] += weight[i];
l = 0;
while (q->x[i][0][l] == 0.0)
l++;
basefreq2[l] += weight[i];
basetable[k][l] += weight[i];
}
vv = lndet(basetable);
if (vv == 99.0) {
printf("\nNegative or zero determinant for distance between species");
printf(" %ld and %ld\n", m, n);
printf(" -1.0 WAS WRITTEN\n");
baddists = true;
}
vv = -0.25*(vv - 0.5*(log(basefreq1[0])+log(basefreq1[1])
+log(basefreq1[2])+log(basefreq1[3])
+log(basefreq2[0])+log(basefreq2[1])
+log(basefreq2[2])+log(basefreq2[3])));
}
if (similarity) {
if (denominator < 1.0) {
printf("\nWARNING: SPECIES %3ld AND %3ld HAVE NO BASES THAT", m, n);
printf(" CAN BE COMPARED\n");
printf(" -1.0 WAS WRITTEN\n");
baddists = true;
}
vv = (double)numerator / denominator;
}
*v = vv;
} /* makev */
void makedists(void)
{
/* compute distance matrix */
long i, j;
double v;
inittable();
for (i = 0; i < endsite; i++)
weightrat[i] = weight[i] * rate[category[alias[i] - 1] - 1];
if (progress) {
printf("Distances calculated for species\n");
#ifdef WIN32
phyFillScreenColor();
#endif
}
for (i = 0; i < spp; i++)
if (similarity)
d[i][i] = 1.0;
else
d[i][i] = 0.0;
baddists = false;
for (i = 1; i < spp; i++) {
if (progress) {
printf(" ");
for (j = 0; j < nmlngth; j++)
putchar(nayme[i - 1][j]);
printf(" ");
}
for (j = i + 1; j <= spp; j++) {
makev(i, j, &v);
d[i - 1][j - 1] = v;
d[j - 1][i - 1] = v;
if (progress) {
putchar('.');
fflush(stdout);
}
}
if (progress) {
putchar('\n');
#ifdef WIN32
phyFillScreenColor();
#endif
}
}
if (progress) {
printf(" ");
for (j = 0; j < nmlngth; j++)
putchar(nayme[spp - 1][j]);
putchar('\n');
}
for (i = 0; i < spp; i++) {
for (j = 0; j < endsite; j++)
free(nodep[i]->x[j]);
free(nodep[i]->x);
}
} /* makedists */
void writedists(void)
{
/* write out distances */
char **names;
names = stringnames_new();
output_matrix_d(outfile, d, spp, spp, names, names, matrix_flags);
stringnames_delete(names);
if (progress)
printf("\nDistances written to file \"%s\"\n\n", outfilename);
} /* writedists */
int main(int argc, Char *argv[])
{ /* DNA Distances by Maximum Likelihood */
#ifdef MAC
argc = 1; /* macsetup("Dnadist",""); */
argv[0] = "Dnadist";
#endif
init(argc, argv);
emboss_getoptions("fdnadist", argc, argv);
ibmpc = IBMCRT;
ansi = ANSICRT;
firstset = true;
doinit();
ttratio0 = ttratio;
for (ith = 1; ith <= datasets; ith++) {
ttratio = ttratio0;
getinput();
if (ith == 1)
firstset = false;
if (datasets > 1 && progress)
printf("Data set # %ld:\n\n",ith);
makedists();
writedists();
}
FClose(infile);
FClose(outfile);
#ifdef MAC
fixmacfile(outfilename);
#endif
printf("Done.\n\n");
#ifdef WIN32
phyRestoreConsoleAttributes();
#endif
embExit();
return 0;
} /* DNA Distances by Maximum Likelihood */
PHYLIPNEW-3.69.650/src/dnamove.c 0000664 0001750 0001750 00000157457 11616234204 012674 0000000 0000000
#include "phylip.h"
#include "moves.h"
#include "seq.h"
/* version 3.6. (c) Copyright 1993-2002 by the University of Washington.
Written by Joseph Felsenstein, Akiko Fuseki, Sean Lamont, and Andrew Keeffe.
Permission is granted to copy and use this program provided no fee is
charged for it and provided that this copyright notice is not removed. */
#define maxsz 999 /* size of pointer array for the undo trees */
/* this can be large without eating memory */
typedef struct treeset_t {
node *root;
pointarray nodep;
pointarray treenode;
long nonodes;
boolean waswritten, hasmult, haslengths, nolengths, initialized;
} treeset_t;
treeset_t treesets[2];
node **treeone, **treetwo;
typedef enum {
horiz, vert, up, overt, upcorner, midcorner, downcorner, aa, cc, gg, tt, question
} chartype;
typedef enum {
rearr, flipp, reroott, none
} rearrtype;
typedef struct gbase2 {
baseptr2 base2;
struct gbase2 *next;
} gbase2;
typedef enum {
arb, use, spec
} howtree;
typedef enum {beforenode, atnode} movet;
movet fromtype;
typedef node **pointptr;
AjPSeqset* seqsets = NULL;
AjPPhyloProp phyloweights = NULL;
AjPPhyloTree* phylotrees;
#ifndef OLDC
/* function prototypes */
void dnamove_gnu(gbases **);
void dnamove_chuck(gbases *);
void emboss_getoptions(char *pgm, int argc, char *argv[]);
void inputoptions(void);
void allocrest(void);
void doinput(void);
void configure(void);
void prefix(chartype);
void postfix(chartype);
void makechar(chartype);
void dnamove_add(node *, node *, node *);
void dnamove_re_move(node **, node **);
void evaluate(node *);
void dnamove_reroot(node *);
void firstrav(node *, long);
void dnamove_hyptrav(node *, long *, long, boolean *);
void grwrite(chartype, long, long *);
void dnamove_drawline(long);
void dnamove_printree(void);
void arbitree(void);
void yourtree(void);
void initdnamovenode(node **, node **, node *, long, long, long *,
long *, initops, pointarray, pointarray, Char *, Char *,
char**);
void buildtree(void);
void setorder(void);
void mincomp(void);
void rearrange(void);
void dnamove_nextinc(void);
void dnamove_nextchar(void);
void dnamove_prevchar(void);
void dnamove_show(void);
void tryadd(node *, node **, node **, double *);
void addpreorder(node *, node *, node *, double *);
void try(void);
void undo(void);
void treewrite(boolean);
void clade(void);
void flip(long);
void changeoutgroup(void);
void redisplay(void);
void treeconstruct(void);
void maketriad(node **, long);
void newdnamove_hyptrav(node *, long *, long, long, boolean,
pointarray);
void prepare_node(node *p);
void dnamove_copynode(node *fromnode, node *tonode);
node *copytrav(node *p);
void chucktree(node *p);
void numdesctrav(node *p);
void copytree(void);
void makeweights(void);
void add_at(node *below, node *newtip, node *newfork);
void add_before(node *atnode, node *newtip);
void add_child(node *parent, node *newchild);
void newdnamove_hyptrav(node *r_, long *hypset_,
long b1, long b2, boolean bottom_,
pointarray treenode);
void newdnamove_hypstates(long chars, node *root, pointarray treenode);
void consolidatetree(long index);
void fliptrav(node *p, boolean recurse);
/* function prototypes */
#endif
char infilename[FNMLNGTH],intreename[FNMLNGTH], weightfilename[FNMLNGTH];
node *root;
const char* outtreename;
AjPFile embossouttree;
long chars, screenlines, col, treelines, leftedge, topedge, vmargin,
hscroll, vscroll, scrollinc, screenwidth, farthest, whichtree, othertree;
boolean weights, thresh, waswritten;
boolean usertree, goteof, firsttree, haslengths; /*treeread variables*/
pointarray nodep; /*treeread variables*/
node *grbg = NULL; /*treeread variables*/
long *zeros; /*treeread variables*/
pointptr treenode; /* pointers to all nodes in tree */
double threshold;
double *threshwt;
boolean reversed[(long)question - (long)horiz + 1];
boolean graphic[(long)question - (long)horiz + 1];
unsigned char chh[(long)question - (long)horiz + 1];
howtree how;
gbases *garbage;
char *progname;
/* Local variables for treeconstruct, propogated global for C version: */
long dispchar, atwhat, what, fromwhere, towhere, oldoutgrno, compatible;
double like, bestyet, gotlike;
boolean display, newtree, changed, subtree, written, oldwritten, restoring,
wasleft, oldleft, earlytree;
steptr necsteps;
boolean *in_tree;
long sett[31];
steptr numsteps;
node *nuroot;
rearrtype lastop;
Char ch;
boolean *names;
void maketriad(node **p, long index)
{
/* Initiate an internal node with stubs for two children */
long i, j;
node *q;
q = NULL;
for (i = 1; i <= 3; i++) {
gnu(&grbg, p);
(*p)->index = index;
(*p)->hasname = false;
(*p)->haslength = false;
(*p)->deleted=false;
(*p)->deadend=false;
(*p)->onebranch=false;
(*p)->onebranchhaslength=false;
if(!(*p)->base)
(*p)->base = (baseptr)Malloc(chars*sizeof(long));
if(!(*p)->numnuc)
(*p)->numnuc = (nucarray *)Malloc(endsite*sizeof(nucarray));
if(!(*p)->numsteps)
(*p)->numsteps = (steptr)Malloc(endsite*sizeof(long));
for (j=0;jnayme[j] = '\0';
(*p)->next = q;
q = *p;
}
(*p)->next->next->next = *p;
q = (*p)->next;
while (*p != q) {
(*p)->back = NULL;
(*p)->tip = false;
*p = (*p)->next;
}
treenode[index - 1] = *p;
} /* maketriad */
void prepare_node(node *p) {
/* This function allocates the base, numnuc and numsteps arrays for
a node. Because a node can change roles between tip, internal and
ring member, all nodes need to have these in case they are used.
*/
p->base = (baseptr)Malloc(chars*sizeof(long));
p->numnuc = (nucarray *)Malloc(endsite*sizeof(nucarray));
p->numsteps = (steptr)Malloc(endsite*sizeof(long));
} /* prepare_tip */
void dnamove_gnu(gbases **p)
{
/* this and the following are do-it-yourself garbage collectors.
Make a new node or pull one off the garbage list */
if (garbage != NULL) {
*p = garbage;
garbage = garbage->next;
} else {
*p = (gbases *)Malloc(sizeof(gbases));
(*p)->base = (baseptr2)Malloc(chars*sizeof(long));
}
(*p)->next = NULL;
} /* dnamove_gnu */
void dnamove_chuck(gbases *p)
{
/* collect garbage on p -- put it on front of garbage list */
p->next = garbage;
garbage = p;
} /* dnamove_chuck */
void dnamove_copynode(node *fromnode, node *tonode)
{
/* Copy the contents of a node from fromnode to tonode. */
int i = 0;
/*
printf("copynode: fromnode = %d, tonode = %d\n",
fromnode->index,tonode->index);
printf("copynode: fromnode->base = %ld, tonode->base = %ld\n",
fromnode->base,tonode->base);
*/
memcpy(tonode->base, fromnode->base, chars*sizeof(long));
/*
printf("copynode: fromnode->numnuc = %ld, tonode->numnuc = %ld\n",
fromnode->numnuc,tonode->numnuc);
*/
if (fromnode->numnuc != NULL)
memcpy(tonode->numnuc, fromnode->numnuc, endsite*sizeof(nucarray));
if (fromnode->numsteps != NULL)
memcpy(tonode->numsteps, fromnode->numsteps, endsite*sizeof(long));
tonode->numdesc = fromnode->numdesc;
tonode->state = fromnode->state;
tonode->index = fromnode->index;
tonode->tip = fromnode->tip;
for (i=0;inayme[i] = fromnode->nayme[i];
} /* dnamove_copynode */
node *copytrav(node *p)
{
/* Traverse the tree from p on down, copying nodes to the other tree */
node *q, *newnode, *newnextnode, *temp;
gnu(&grbg, &newnode);
if(!newnode->base)
newnode->base = (baseptr)Malloc(chars*sizeof(long));
if(!newnode->numnuc)
newnode->numnuc = (nucarray *)Malloc(endsite*sizeof(nucarray));
if(!newnode->numsteps)
newnode->numsteps = (steptr)Malloc(endsite*sizeof(long));
dnamove_copynode(p,newnode);
if (treenode[p->index-1] == p)
treesets[othertree].treenode[p->index-1] = newnode;
/* if this is a tip, return now */
if (p->tip)
return newnode;
/* go around the ring, copying as we go */
q = p->next;
gnu(&grbg, &newnextnode);
if(!newnextnode->base)
newnextnode->base = (baseptr)Malloc(chars*sizeof(long));
if(!newnextnode->numnuc)
newnextnode->numnuc = (nucarray *)Malloc(endsite*sizeof(nucarray));
if(!newnextnode->numsteps)
newnextnode->numsteps = (steptr)Malloc(endsite*sizeof(long));
dnamove_copynode(q, newnextnode);
newnode->next = newnextnode;
do {
newnextnode->back = copytrav(q->back);
newnextnode->back->back = newnextnode;
q = q->next;
if (q == p)
newnextnode->next = newnode;
else {
temp = newnextnode;
gnu(&grbg, &newnextnode);
if(!newnextnode->base)
newnextnode->base = (baseptr)Malloc(chars*sizeof(long));
if(!newnextnode->numnuc)
newnextnode->numnuc = (nucarray *)Malloc(endsite*sizeof(nucarray));
if(!newnextnode->numsteps)
newnextnode->numsteps = (steptr)Malloc(endsite*sizeof(long));
dnamove_copynode(q, newnextnode);
temp->next = newnextnode;
}
} while (q != p);
return newnode;
} /* copytrav */
void numdesctrav(node *p)
{
node *q;
long childcount = 0;
if (p->tip) {
p->numdesc = 0;
return;
}
q = p->next;
do {
numdesctrav(q->back);
childcount++;
q = q->next;
} while (q != p);
p->numdesc = childcount;
} /* numdesctrav */
void chucktree(node *p)
{
/* recursively run through a tree and chuck all of its nodes,
putting them on the garbage list */
int i, numNodes = 1;
node *q, *r;
/* base case -- tip */
if(p->tip){
chuck(&grbg, p);
return;
}
/* recursively callchuck tree on all decendants */
q = p->next;
while(q != p){
chucktree(q->back);
numNodes++;
q = q->next;
}
/* now chuck all sub-nodes in the node ring */
for(i=0 ; i < numNodes ; i++){
r = q->next;
chuck(&grbg, q);
q = r;
}
} /* chucktree */
void copytree(void)
{
/* Make a complete copy of the current tree for undo purposes */
if (whichtree == 1)
othertree = 0;
else
othertree = 1;
if(treesets[othertree].root){
chucktree(treesets[othertree].root);
}
treesets[othertree].root = copytrav(root);
treesets[othertree].nonodes = nonodes;
treesets[othertree].waswritten = waswritten;
treesets[othertree].initialized = true;
} /* copytree */
void emboss_getoptions(char *pgm, int argc, char *argv[])
{
AjPStr initialtree = NULL;
how = arb;
usertree = false;
goteof = false;
outgrno = 1;
outgropt = false;
thresh = false;
weights = false;
screenlines = 24;
scrollinc = 20;
screenwidth = 80;
embInitPV(pgm, argc, argv, "PHYLIPNEW",VERSION);
seqsets = ajAcdGetSeqsetall("sequence");
outgrno = ajAcdGetInt("outgrno");
if(outgrno != 0) outgropt = true;
else outgrno = 1;
phyloweights = ajAcdGetProperties("weights");
if(phyloweights) weights = true;
thresh = ajAcdGetToggle("dothreshold");
if(thresh) threshold = ajAcdGetFloat("threshold");
initialtree = ajAcdGetListSingle("initialtree");
if(ajStrMatchC(initialtree, "a")) how = arb;
if(ajStrMatchC(initialtree, "u")) how = use;
if(ajStrMatchC(initialtree, "s")) {
how = spec;
phylotrees = ajAcdGetTree("intreefile");
usertree = true;
}
screenwidth = ajAcdGetInt("screenwidth");
screenlines = ajAcdGetInt("screenlines");
if (scrollinc < screenwidth / 2.0) hscroll = scrollinc;
else hscroll = screenwidth / 2;
if (scrollinc < screenlines / 2.0) vscroll = scrollinc;
else vscroll = screenlines / 2;
embossouttree = ajAcdGetOutfile("outtreefile");
emboss_openfile(embossouttree, &outtree, &outtreename);
} /* emboss_getoptions */
void inputoptions(void)
{
/* input the information on the options */
long i;
for (i = 0; i < (chars); i++)
weight[i] = 1;
if (weights){
inputweightsstr(phyloweights->Str[0], chars, weight, &weights);
printweights(stdout, 0, chars, weight, "Sites");
}
if (!thresh)
threshold = spp;
for (i = 0; i < (chars); i++)
threshwt[i] = threshold * weight[i];
} /* inputoptions */
void allocrest(void)
{
long i;
nayme = (naym *)Malloc(spp*sizeof(naym));
in_tree = (boolean *)Malloc(nonodes*sizeof(boolean));
weight = (steptr)Malloc(chars*sizeof(long));
numsteps = (steptr)Malloc(chars*sizeof(long));
necsteps = (steptr)Malloc(chars*sizeof(long));
threshwt = (double *)Malloc(chars*sizeof(double));
alias = (long *)Malloc(chars*sizeof(long)); /* from dnapars */
ally = (long *)Malloc(chars*sizeof(long)); /* from dnapars */
y = (Char **)Malloc(spp*sizeof(Char *)); /* from dnapars */
for (i = 0; i < spp; i++) /* from dnapars */
y[i] = (Char *)Malloc(chars*sizeof(Char)); /* from dnapars */
location = (long *)Malloc(chars*sizeof(long)); /* from dnapars */
} /* allocrest */
void makeweights(void)
{
/* make up weights vector to avoid duplicate computations */
long i;
for (i = 1; i <= chars; i++) {
alias[i - 1] = i;
ally[i - 1] = i;
}
endsite = 0;
for (i = 1; i <= chars; i++) {
if (ally[i - 1] == i)
endsite++;
}
for (i = 1; i <= endsite; i++)
location[alias[i - 1] - 1] = i;
if (!thresh)
threshold = spp;
zeros = (long *)Malloc(endsite*sizeof(long));
for (i = 0; i < endsite; i++)
zeros[i] = 0;
} /* makeweights */
void doinput(void)
{
/* reads the input data */
inputnumbersseq(seqsets[0], &spp, &chars, &nonodes, 1);
printf("%2ld species, %3ld sites\n", spp, chars);
allocrest();
inputoptions();
alloctree(&treenode, nonodes, usertree);
setuptree(treenode, nonodes, usertree);
seq_inputdata(seqsets[0], chars);
makeweights();
makevalues(treenode, zeros, usertree);
} /* doinput */
void configure(void)
{
/* configure to machine -- set up special characters */
chartype a;
for (a = horiz; (long)a <= (long)question; a = (chartype)((long)a + 1))
reversed[(long)a] = false;
for (a = horiz; (long)a <= (long)question; a = (chartype)((long)a + 1))
graphic[(long)a] = false;
if (ibmpc) {
chh[(long)horiz] = 205;
graphic[(long)horiz] = true;
chh[(long)vert] = 186;
graphic[(long)vert] = true;
chh[(long)up] = 186;
graphic[(long)up] = true;
chh[(long)overt] = 205;
graphic[(long)overt] = true;
chh[(long)upcorner] = 200;
graphic[(long)upcorner] = true;
chh[(long)midcorner] = 204;
graphic[(long)midcorner] = true;
chh[(long)downcorner] = 201;
graphic[(long)downcorner] = true;
chh[(long)aa] = 176;
chh[(long)cc] = 178;
chh[(long)gg] = 177;
chh[(long)tt] = 219;
chh[(long)question] = '\001';
return;
}
if (ansi) {
chh[(long)horiz] = ' ';
reversed[(long)horiz] = true;
chh[(long)vert] = chh[(long)horiz];
reversed[(long)vert] = true;
chh[(long)up] = 'x';
graphic[(long)up] = true;
chh[(long)overt] = 'q';
graphic[(long)overt] = true;
chh[(long)upcorner] = 'm';
graphic[(long)upcorner] = true;
chh[(long)midcorner] = 't';
graphic[(long)midcorner] = true;
chh[(long)downcorner] = 'l';
graphic[(long)downcorner] = true;
chh[(long)aa] = 'a';
reversed[(long)aa] = true;
chh[(long)cc] = 'c';
reversed[(long)cc] = true;
chh[(long)gg] = 'g';
reversed[(long)gg] = true;
chh[(long)tt] = 't';
reversed[(long)tt] = true;
chh[(long)question] = '?';
reversed[(long)question] = true;
return;
}
chh[(long)horiz] = '=';
chh[(long)vert] = ' ';
chh[(long)up] = '!';
chh[(long)upcorner] = '`';
chh[(long)midcorner] = '+';
chh[(long)downcorner] = ',';
chh[(long)overt] = '-';
chh[(long)aa] = 'a';
chh[(long)cc] = 'c';
chh[(long)gg] = 'g';
chh[(long)tt] = 't';
chh[(long)question] = '.';
} /* configure */
void prefix(chartype a)
{
/* give prefix appropriate for this character */
if (reversed[(long)a])
prereverse(ansi);
if (graphic[(long)a])
pregraph2(ansi);
} /* prefix */
void postfix(chartype a)
{
/* give postfix appropriate for this character */
if (reversed[(long)a])
postreverse(ansi);
if (graphic[(long)a])
postgraph2(ansi);
} /* postfix */
void makechar(chartype a)
{
/* print out a character with appropriate prefix or postfix */
prefix(a);
putchar(chh[(long)a]);
postfix(a);
} /* makechar */
void add_at(node *below, node *newtip, node *newfork)
{
/* inserts the nodes newfork and its left descendant, newtip,
to the tree. below becomes newfork's right descendant */
node *leftdesc, *rtdesc;
if (below != treenode[below->index - 1])
below = treenode[below->index - 1];
if (newfork == NULL) {
nonodes++;
maketriad (&newfork, nonodes);
}
if (below->back != NULL) {
below->back->back = newfork;
}
newfork->back = below->back;
leftdesc = newtip;
rtdesc = below;
rtdesc->back = newfork->next->next;
newfork->next->next->back = rtdesc;
newfork->next->back = leftdesc;
leftdesc->back = newfork->next;
if (root == below)
root = newfork;
root->back = NULL;
} /* add_at */
void add_before(node *atnode, node *newtip)
{
/* inserts the node newtip together with its ancestral fork
into the tree next to the node atnode. */
node *q;
if (atnode != treenode[atnode->index - 1])
atnode = treenode[atnode->index - 1];
q = treenode[newtip->index-1]->back;
if (q != NULL) {
q = treenode[q->index-1];
if (newtip == q->next->next->back) {
q->next->back = newtip;
newtip->back = q->next;
q->next->next->back = NULL;
}
}
if (newtip->back != NULL) {
add_at(atnode, newtip, treenode[newtip->back->index-1]);
} else {
add_at(atnode, newtip, NULL);
}
} /* add_before */
void add_child(node *parent, node *newchild)
{
/* adds the node newchild into the tree as the last child of parent */
int i;
node *newnode, *q;
if (parent != treenode[parent->index - 1])
parent = treenode[parent->index - 1];
gnu(&grbg, &newnode);
newnode->tip = false;
newnode->deleted=false;
newnode->deadend=false;
newnode->onebranch=false;
newnode->onebranchhaslength=false;
for (i=0;inayme[i] = '\0';
newnode->index = parent->index;
if(!newnode->base)
newnode->base = (baseptr)Malloc(chars*sizeof(long));
if(!newnode->numnuc)
newnode->numnuc = (nucarray *)Malloc(endsite*sizeof(nucarray));
if(!newnode->numsteps)
newnode->numsteps = (steptr)Malloc(endsite*sizeof(long));
q = parent;
do {
q = q->next;
} while (q->next != parent);
newnode->next = parent;
q->next = newnode;
newnode->back = newchild;
newchild->back = newnode;
if (newchild->haslength) {
newnode->length = newchild->length;
newnode->haslength = true;
} else
newnode->haslength = false;
} /* add_child */
void dnamove_add(node *below, node *newtip, node *newfork)
{
/* inserts the nodes newfork and its left descendant, newtip,
to the tree. below becomes newfork's right descendant */
boolean putleft;
node *leftdesc, *rtdesc;
if (below != treenode[below->index - 1])
below = treenode[below->index - 1];
if (below->back != NULL)
below->back->back = newfork;
newfork->back = below->back;
putleft = true;
if (restoring)
putleft = wasleft;
if (putleft) {
leftdesc = newtip;
rtdesc = below;
} else {
leftdesc = below;
rtdesc = newtip;
}
rtdesc->back = newfork->next->next;
newfork->next->next->back = rtdesc;
newfork->next->back = leftdesc;
leftdesc->back = newfork->next;
if (root == below)
root = newfork;
root->back = NULL;
newfork->numdesc = 2;
} /* dnamove_add */
void dnamove_re_move(node **item, node **fork)
{
/* Removes node item from the tree. If item has one sibling,
removes its ancestor, fork, from the tree as well and attach
item's sib to fork's ancestor. In this case, it returns a pointer
to the removed fork node which is still attached to item.
*/
node *p=NULL, *q;
int nodecount;
if ((*item)->back == NULL) {
*fork = NULL;
return;
}
*fork = treenode[(*item)->back->index - 1];
nodecount = 0;
if ((*fork)->next->back == *item)
p = *fork;
q = (*fork)->next;
do {
nodecount++;
if (q->next->back == *item)
p = q;
q = q->next;
} while (*fork != q);
if (nodecount > 2)
{
fromtype = atnode;
p->next = (*item)->back->next;
chuck(&grbg, (*item)->back);
(*item)->back = NULL;
*fork = NULL;
} else {
/* traditional (binary tree) remove code */
if (*item == (*fork)->next->back) {
if (root == *fork)
root = (*fork)->next->next->back;
} else {
if (root == *fork)
root = (*fork)->next->back;
}
fromtype = beforenode;
/* stitch nodes together, leaving out item */
p = (*item)->back->next->back;
q = (*item)->back->next->next->back;
if (p != NULL)
p->back = q;
if (q != NULL)
q->back = p;
if (haslengths) {
if (p != NULL && q != NULL) {
p->length += q->length;
q->length = p->length;
} else
(*item)->length = (*fork)->next->length + (*fork)->next->next->length;
}
(*fork)->back = NULL;
p = (*fork)->next;
while (p != *fork) {
p->back = NULL;
p = p->next;
}
(*item)->back = NULL;
} /* endif nodecount > 2 else */
} /* dnamove_re_move */
void evaluate(node *r)
{
/* determines the number of steps needed for a tree. this is
the minimum number of steps needed to evolve sequences on
this tree */
long i, steps;
double sum;
compatible = 0;
sum = 0.0;
for (i = 0; i < (chars); i++)
numsteps[i] = 0;
/* set numdesc at each node to reflect current number of descendants */
numdesctrav(root);
postorder(r);
for (i = 0; i < endsite; i++) {
steps = r->numsteps[i];
if (steps <= threshwt[i]) {
sum += steps;
} else {
sum += threshwt[i];
}
if (steps <= necsteps[i] && !earlytree)
compatible += weight[i];
}
like = -sum;
} /* evaluate */
void dnamove_reroot(node *outgroup)
{
/* Reorient tree so that outgroup is by itself on the left of the root */
node *p, *q, *r;
long nodecount = 0;
double templen;
if(outgroup->back->index == root->index)
return;
q = root->next;
do { /* when this loop exits, p points to the internal */
p = q; /* node to the right of root */
nodecount++;
q = p->next;
} while (q != root);
r = p;
/* reorient nodep array
The nodep array must point to the ring member of each ring
that is closest to the root. The while loop changes the ring member
pointed to by treenode[] for those nodes that will have their
orientation changed by the reroot operation.
*/
p = outgroup->back;
while (p->index != root->index) {
q = treenode[p->index - 1]->back;
treenode[p->index - 1] = p;
p = q;
}
if (nodecount > 2)
treenode[p->index - 1] = p;
/* If nodecount > 2, the current node ring to which root is pointing
will remain in place and root will point somewhere else. */
/* detach root from old location */
if (nodecount > 2) {
r->next = root->next;
root->next = NULL;
nonodes++;
maketriad(&root, nonodes);
if (haslengths) {
/* root->haslength remains false, or else treeout() will generate
a bogus extra length */
root->next->haslength = true;
root->next->next->haslength = true;
}
} else { /* if (nodecount > 2) else */
q = root->next;
q->back->back = r->back;
r->back->back = q->back;
if (haslengths) {
r->back->length = r->back->length + q->back->length;
q->back->length = r->back->length;
}
} /* if (nodecount > 2) endif */
/* tie root into new location */
root->next->back = outgroup;
root->next->next->back = outgroup->back;
outgroup->back->back = root->next->next;
outgroup->back = root->next;
/* place root equidistant between left child (outgroup) and
right child by deviding outgroup's length */
if (haslengths) {
templen = outgroup->length / 2.0;
outgroup->length = templen;
outgroup->back->length = templen;
root->next->next->length = templen;
root->next->next->back->length = templen;
}
} /* dnamove_reroot */
void newdnamove_hyptrav(node *r_, long *hypset_, long b1, long b2, boolean bottom_,
pointarray treenode)
{
/* compute, print out states at one interior node */
struct LOC_hyptrav Vars;
long i, j, k;
long largest;
gbases *ancset;
nucarray *tempnuc;
node *p, *q;
Vars.bottom = bottom_;
Vars.r = r_;
Vars.hypset = hypset_;
dnamove_gnu(&ancset);
tempnuc = (nucarray *)Malloc(endsite*sizeof(nucarray));
Vars.maybe = false;
Vars.nonzero = false;
if (!Vars.r->tip)
zeronumnuc(Vars.r, endsite);
for (i = b1 - 1; i < b2; i++) {
j = location[ally[i] - 1];
Vars.anc = Vars.hypset[j - 1];
if (!Vars.r->tip) {
p = Vars.r->next;
for (k = (long)A; k <= (long)O; k++)
if (Vars.anc & (1 << k))
Vars.r->numnuc[j - 1][k]++;
do {
for (k = (long)A; k <= (long)O; k++)
if (p->back->base[j - 1] & (1 << k))
Vars.r->numnuc[j - 1][k]++;
p = p->next;
} while (p != Vars.r);
largest = getlargest(Vars.r->numnuc[j - 1]);
Vars.tempset = 0;
for (k = (long)A; k <= (long)O; k++) {
if (Vars.r->numnuc[j - 1][k] == largest)
Vars.tempset |= (1 << k);
}
Vars.r->base[j - 1] = Vars.tempset;
}
if (!Vars.bottom)
Vars.anc = treenode[Vars.r->back->index - 1]->base[j - 1];
Vars.nonzero = (Vars.nonzero || (Vars.r->base[j - 1] & Vars.anc) == 0);
Vars.maybe = (Vars.maybe || Vars.r->base[j - 1] != Vars.anc);
}
j = location[ally[dispchar - 1] - 1];
Vars.tempset = Vars.r->base[j - 1];
Vars.anc = Vars.hypset[j - 1];
if (!Vars.bottom)
Vars.anc = treenode[Vars.r->back->index - 1]->base[j - 1];
r_->state = '?';
if (Vars.tempset == (1 << A))
r_->state = 'A';
if (Vars.tempset == (1 << C))
r_->state = 'C';
if (Vars.tempset == (1 << G))
r_->state = 'G';
if (Vars.tempset == (1 << T))
r_->state = 'T';
Vars.bottom = false;
if (!Vars.r->tip) {
memcpy(tempnuc, Vars.r->numnuc, endsite*sizeof(nucarray));
q = Vars.r->next;
do {
memcpy(Vars.r->numnuc, tempnuc, endsite*sizeof(nucarray));
for (i = b1 - 1; i < b2; i++) {
j = location[ally[i] - 1];
for (k = (long)A; k <= (long)O; k++)
if (q->back->base[j - 1] & (1 << k))
Vars.r->numnuc[j - 1][k]--;
largest = getlargest(Vars.r->numnuc[j - 1]);
ancset->base[j - 1] = 0;
for (k = (long)A; k <= (long)O; k++)
if (Vars.r->numnuc[j - 1][k] == largest)
ancset->base[j - 1] |= (1 << k);
if (!Vars.bottom)
Vars.anc = ancset->base[j - 1];
}
newdnamove_hyptrav(q->back, ancset->base, b1, b2, Vars.bottom,
treenode);
q = q->next;
} while (q != Vars.r);
}
dnamove_chuck(ancset);
} /* newdnamove_hyptrav */
void newdnamove_hypstates(long chars, node *root, pointarray treenode)
{
/* fill in and describe states at interior nodes */
/* used in dnacomp, dnapars, & dnapenny */
long i, n;
baseptr nothing;
/* garbage is passed along without usage to newdnamove_hyptrav,
which also does not use it. */
nothing = (baseptr)Malloc(endsite*sizeof(long));
for (i = 0; i < endsite; i++)
nothing[i] = 0;
for (i = 1; i <= ((chars - 1) / 40 + 1); i++) {
putc('\n', outfile);
n = i * 40;
if (n > chars)
n = chars;
newdnamove_hyptrav(root, nothing, i * 40 - 39, n, true, treenode);
}
free(nothing);
} /* newdnamove_hypstates */
void grwrite(chartype c, long num, long *pos)
{
long i;
prefix(c);
for (i = 1; i <= num; i++) {
if ((*pos) >= leftedge && (*pos) - leftedge + 1 < screenwidth)
putchar(chh[(long)c]);
(*pos)++;
}
postfix(c);
} /* grwrite */
void dnamove_drawline(long i)
{
/* draws one row of the tree diagram by moving up tree */
node *p, *q, *r, *first =NULL, *last =NULL;
long n, j, pos;
boolean extra, done;
Char st;
chartype c, d;
pos = 1;
p = nuroot;
q = nuroot;
extra = false;
if (i == p->ycoord && (p == root || subtree)) {
extra = true;
c = overt;
if (display) {
switch (p->state) {
case 'A':
c = aa;
break;
case 'C':
c = cc;
break;
case 'G':
c = gg;
break;
case 'T':
c = tt;
break;
case '?':
c = question;
break;
}
}
if ((subtree))
stwrite("Subtree:", 8, &pos, leftedge, screenwidth);
if (p->index >= 100)
nnwrite(p->index, 3, &pos, leftedge, screenwidth);
else if (p->index >= 10) {
grwrite(c, 1, &pos);
nnwrite(p->index, 2, &pos, leftedge, screenwidth);
} else {
grwrite(c, 2, &pos);
nnwrite(p->index, 1, &pos, leftedge, screenwidth);
}
} else {
if ((subtree))
stwrite(" ", 10, &pos, leftedge, screenwidth);
else
stwrite(" ", 2, &pos, leftedge, screenwidth);
}
do {
if (!p->tip) {
r = p->next;
done = false;
do {
if (i >= r->back->ymin && i <= r->back->ymax) {
q = r->back;
done = true;
}
r = r->next;
} while (!(done || r == p));
first = p->next->back;
r = p->next;
while (r->next != p)
r = r->next;
last = r->back;
}
done = (p == q);
n = p->xcoord - q->xcoord;
if (n < 3 && !q->tip)
n = 3;
if (extra) {
n--;
extra = false;
}
if (q->ycoord == i && !done) {
c = overt;
if (q == first)
d = downcorner;
else if (q == last)
d = upcorner;
else if ((long)q->ycoord == (long)p->ycoord)
d = c;
else
d = midcorner;
if (display) {
switch (q->state) {
case 'A':
c = aa;
break;
case 'C':
c = cc;
break;
case 'G':
c = gg;
break;
case 'T':
c = tt;
break;
case '?':
c = question;
break;
}
d = c;
}
if (n > 1) {
grwrite(d, 1, &pos);
grwrite(c, n - 3, &pos);
}
if (q->index >= 100)
nnwrite(q->index, 3, &pos, leftedge, screenwidth);
else if (q->index >= 10) {
grwrite(c, 1, &pos);
nnwrite(q->index, 2, &pos, leftedge, screenwidth);
} else {
grwrite(c, 2, &pos);
nnwrite(q->index, 1, &pos, leftedge, screenwidth);
}
extra = true;
} else if (!q->tip) {
if (last->ycoord > i && first->ycoord < i && i != p->ycoord) {
c = up;
if (i < p->ycoord)
st = p->next->back->state;
else
st = p->next->next->back->state;
if (display) {
switch (st) {
case 'A':
c = aa;
break;
case 'C':
c = cc;
break;
case 'G':
c = gg;
break;
case 'T':
c = tt;
break;
case '?':
c = question;
break;
}
}
grwrite(c, 1, &pos);
chwrite(' ', n - 1, &pos, leftedge, screenwidth);
} else
chwrite(' ', n, &pos, leftedge, screenwidth);
} else
chwrite(' ', n, &pos, leftedge, screenwidth);
if (p != q)
p = q;
} while (!done);
if (p->ycoord == i && p->tip) {
n = 0;
for (j = 1; j <= nmlngth; j++) {
if (nayme[p->index - 1][j - 1] != '\0')
n = j;
}
chwrite(':', 1, &pos, leftedge, screenwidth);
for (j = 0; j < n; j++)
chwrite(nayme[p->index - 1][j], 1, &pos, leftedge, screenwidth);
}
putchar('\n');
} /* dnamove_drawline */
void dnamove_printree(void)
{
/* prints out diagram of the tree */
long tipy;
long i, dow;
if (!subtree)
nuroot = root;
if (changed || newtree)
evaluate(root);
if (display) {
outfile = stdout;
newdnamove_hypstates(chars, root, treenode);
}
#ifdef WIN32
if(ibmpc || ansi)
phyClearScreen();
else
printf("\n");
#else
printf((ansi || ibmpc) ? "\033[2J\033[H" : "\n");
#endif
tipy = 1;
dow = down;
if (spp * dow > screenlines && !subtree)
dow--;
printf(" (unrooted)");
if (display) {
printf(" ");
makechar(aa);
printf(":A ");
makechar(cc);
printf(":C ");
makechar(gg);
printf(":G ");
makechar(tt);
printf(":T ");
makechar(question);
printf(":?");
} else
printf(" ");
if (!earlytree) {
printf("%10.1f Steps", -like);
}
if (display)
printf(" SITE%4ld", dispchar);
else
printf(" ");
if (!earlytree) {
printf(" %3ld sites compatible\n", compatible);
}
printf(" ");
if (changed && !earlytree) {
if (-like < bestyet) {
printf(" BEST YET!");
bestyet = -like;
} else if (fabs(-like - bestyet) < 0.000001)
printf(" (as good as best)");
else {
if (-like < gotlike)
printf(" better");
else if (-like > gotlike)
printf(" worse!");
}
}
printf("\n");
farthest = 0;
coordinates(nuroot, &tipy, 1.5, &farthest);
vmargin = 4;
treelines = tipy - dow;
if (topedge != 1) {
printf("** %ld lines above screen **\n", topedge - 1);
vmargin++;
}
if ((treelines - topedge + 1) > (screenlines - vmargin))
vmargin++;
for (i = 1; i <= treelines; i++) {
if (i >= topedge && i < topedge + screenlines - vmargin)
dnamove_drawline(i);
}
if ((treelines - topedge + 1) > (screenlines - vmargin)) {
printf("** %ld", treelines - (topedge - 1 + screenlines - vmargin));
printf(" lines below screen **\n");
}
if (treelines - topedge + vmargin + 1 < screenlines)
putchar('\n');
gotlike = -like;
changed = false;
} /* dnamove_printree */
void arbitree(void)
{
long i;
root = treenode[0];
dnamove_add(treenode[0], treenode[1], treenode[spp]);
for (i = 3; i <= (spp); i++) {
dnamove_add(treenode[spp + i - 3], treenode[i - 1], treenode[spp + i - 2]);
}
} /* arbitree */
void yourtree(void)
{
long i, j;
boolean ok;
root = treenode[0];
dnamove_add(treenode[0], treenode[1], treenode[spp]);
i = 2;
do {
i++;
dnamove_printree();
printf("Add species%3ld: ", i);
for (j = 0; j < nmlngth; j++)
putchar(nayme[i - 1][j]);
do {
printf("\n at or before which node (type number): ");
inpnum(&j, &ok);
ok = (ok && ((j >= 1 && j < i) || (j > spp && j < spp + i - 1)));
if (!ok)
printf("Impossible number. Please try again:\n");
} while (!ok);
if (j >= i) { /* has user chosen a non-tip? if so, offer choice */
do {
printf(" Insert at node (A) or before node (B)? ");
#ifdef WIN32
phyFillScreenColor();
#endif
fflush(stdout);
scanf("%c%*[^\n]", &ch);
getchar();
if (ch == '\n')
ch = ' ';
ch = isupper((int)ch) ? ch : toupper((int)ch);
} while (ch != 'A' && ch != 'B');
}
else ch = 'B'; /* if user has chosen a tip, set Before */
if (j != 0) {
if (ch == 'A') {
if (!treenode[j - 1]->tip) {
add_child(treenode[j - 1], treenode[i - 1]);
}
} else {
printf("dnamove_add(below %ld, newtip %ld, newfork %ld)\n",j-1,i-1,spp+i-2);
dnamove_add(treenode[j - 1], treenode[i - 1], treenode[spp + i - 2]);
} /* endif (before or at node) */
}
} while (i != spp);
} /* yourtree */
void initdnamovenode(node **p, node **grbg, node *q, long len, long nodei,
long *ntips, long *parens, initops whichinit,
pointarray treenode, pointarray nodep, Char *str, Char *ch,
char **treestr)
{
/* initializes a node */
/* LM 7/27 I added this function and the commented lines around */
/* treeread() to get the program running, but all 4 move programs*/
/* are improperly integrated into the v4.0 support files. As is */
/* endsite = chars and this is a patchwork function */
boolean minusread;
double valyew, divisor;
switch (whichinit) {
case bottom:
gnutreenode(grbg, p, nodei, endsite, zeros);
treenode[nodei - 1] = *p;
break;
case nonbottom:
gnutreenode(grbg, p, nodei, endsite, zeros);
break;
case tip:
match_names_to_data (str, treenode, p, spp);
break;
case length:
processlength(&valyew, &divisor, ch, &minusread, treestr, parens);
/* process lengths and discard */
default: /*cases hslength,hsnolength,treewt,unittrwt,iter,*/
break;
}
} /* initdnamovenode */
void buildtree(void)
{
long i, nextnode;
node *p;
long j;
char* treestr;
treeone = (node **)Malloc(maxsz*sizeof(node *));
treetwo = (node **)Malloc(maxsz*sizeof(node *));
treesets[othertree].treenode = treetwo;
changed = false;
newtree = false;
switch (how) {
case arb:
treesets[othertree].treenode = treetwo;
arbitree();
break;
case use:
names = (boolean *)Malloc(spp*sizeof(boolean));
firsttree = true;
nodep = NULL;
nextnode = 0;
haslengths = 0;
for (i = 0; i < endsite; i++)
zeros[i] = 0;
treesets[whichtree].nodep = nodep;
treestr = ajStrGetuniquePtr(&phylotrees[0]->Tree);
treeread(&treestr, &root, treenode, &goteof, &firsttree,
nodep, &nextnode, &haslengths,
&grbg, initdnamovenode,true,nonodes);
for (i = spp; i < (nextnode); i++) {
p = treenode[i];
for (j = 1; j <= 3; j++) {
p->base = (baseptr2)Malloc(chars*sizeof(long));
p = p->next;
}
} /* debug: see comment at initdnamovenode() */
free(names);
FClose(intree);
break;
case spec:
treesets[othertree].treenode = treetwo;
yourtree();
break;
}
if (!outgropt)
outgrno = root->next->back->index;
if (outgropt)
dnamove_reroot(treenode[outgrno - 1]);
} /* buildtree */
void setorder(void)
{
/* sets in order of number of members */
sett[0] = 1L << ((long)A);
sett[1] = 1L << ((long)C);
sett[2] = 1L << ((long)G);
sett[3] = 1L << ((long)T);
sett[4] = 1L << ((long)O);
sett[5] = (1L << ((long)A)) | (1L << ((long)C));
sett[6] = (1L << ((long)A)) | (1L << ((long)G));
sett[7] = (1L << ((long)A)) | (1L << ((long)T));
sett[8] = (1L << ((long)A)) | (1L << ((long)O));
sett[9] = (1L << ((long)C)) | (1L << ((long)G));
sett[10] = (1L << ((long)C)) | (1L << ((long)T));
sett[11] = (1L << ((long)C)) | (1L << ((long)O));
sett[12] = (1L << ((long)G)) | (1L << ((long)T));
sett[13] = (1L << ((long)G)) | (1L << ((long)O));
sett[14] = (1L << ((long)T)) | (1L << ((long)O));
sett[15] = (1L << ((long)A)) | (1L << ((long)C)) | (1L << ((long)G));
sett[16] = (1L << ((long)A)) | (1L << ((long)C)) | (1L << ((long)T));
sett[17] = (1L << ((long)A)) | (1L << ((long)C)) | (1L << ((long)O));
sett[18] = (1L << ((long)A)) | (1L << ((long)G)) | (1L << ((long)T));
sett[19] = (1L << ((long)A)) | (1L << ((long)G)) | (1L << ((long)O));
sett[20] = (1L << ((long)A)) | (1L << ((long)T)) | (1L << ((long)O));
sett[21] = (1L << ((long)C)) | (1L << ((long)G)) | (1L << ((long)T));
sett[22] = (1L << ((long)C)) | (1L << ((long)G)) | (1L << ((long)O));
sett[23] = (1L << ((long)C)) | (1L << ((long)T)) | (1L << ((long)O));
sett[24] = (1L << ((long)G)) | (1L << ((long)T)) | (1L << ((long)O));
sett[25] = (1L << ((long)A)) | (1L << ((long)C)) | (1L << ((long)G)) |
(1L << ((long)T));
sett[26] = (1L << ((long)A)) | (1L << ((long)C)) | (1L << ((long)G)) |
(1L << ((long)O));
sett[27] = (1L << ((long)A)) | (1L << ((long)C)) | (1L << ((long)T)) |
(1L << ((long)O));
sett[28] = (1L << ((long)A)) | (1L << ((long)G)) | (1L << ((long)T)) |
(1L << ((long)O));
sett[29] = (1L << ((long)C)) | (1L << ((long)G)) | (1L << ((long)T)) |
(1L << ((long)O));
sett[30] = (1L << ((long)A)) | (1L << ((long)C)) | (1L << ((long)G)) |
(1L << ((long)T)) | (1L << ((long)O));
} /* setorder */
void mincomp(void)
{
/* computes for each site the minimum number of steps
necessary to accomodate those species already
in the analysis */
long i, j, k;
boolean done;
for (i = 0; i < (chars); i++) {
done = false;
j = 0;
while (!done) {
j++;
done = true;
k = 1;
do {
if (k < nonodes)
done = (done && (treenode[k - 1]->base[i] & sett[j - 1]) != 0);
k++;
} while (k <= spp && done);
}
if (j == 31)
necsteps[i] = 4;
if (j <= 30)
necsteps[i] = 3;
if (j <= 25)
necsteps[i] = 2;
if (j <= 15)
necsteps[i] = 1;
if (j <= 5)
necsteps[i] = 0;
necsteps[i] *= weight[i];
}
} /* mincomp */
void consolidatetree(long index)
{
node *start, *r, *q;
int i;
i = 0;
start = treenode[index - 1];
q = start->next;
while (q != start) {
r = q;
q = q->next;
chuck(&grbg, r);
}
chuck(&grbg, q);
i = index;
while (i <= nonodes) {
r = treenode[i - 1];
if (!(r->tip))
r->index--;
if (!(r->tip)) {
q = r->next;
do {
q->index--;
q = q->next;
} while (r != q && q != NULL);
}
treenode[i - 1] = treenode[i];
i++;
}
nonodes--;
} /* consolidatetree */
void rearrange(void)
{
long i, j, maxinput;
boolean ok1, ok2;
node *p, *q;
char ch;
printf("Remove everything to the right of which node? ");
inpnum(&i, &ok1);
ok1 = (ok1 && i >= 1 && i <= (spp * 2 - 1) && i != root->index);
if (ok1)
ok1 = !treenode[i - 1]->deleted;
if (ok1) {
printf("Add at or before which node? ");
inpnum(&j, &ok2);
ok2 = (ok2 && j >= 1 && j <= (spp * 2 - 1));
if (ok2) {
if (j != root->index)
ok2 = !treenode[treenode[j - 1]->back->index - 1]->deleted;
}
if (ok2) {
/*xx This edit says "j must not be i's parent."
Is this necessary anymore? */
/* ok2 = (nodep[j - 1] != nodep[nodep[i - 1]->back->index - 1]);*/
p = treenode[j - 1];
/* make sure that j is not a descendent of i */
while (p != root) {
ok2 = (ok2 && p != treenode[i - 1]);
p = treenode[p->back->index - 1];
}
if (ok1 && ok2) {
maxinput = 1;
do {
printf("Insert at node (A) or before node (B)? ");
#ifdef WIN32
phyFillScreenColor();
#endif
fflush(stdout);
scanf("%c%*[^\n]", &ch);
getchar();
if (ch == '\n')
ch = ' ';
ch = isupper((int)ch) ? ch : toupper((int)ch);
maxinput++;
if (maxinput == 100) {
printf("ERROR: too many tries at choosing option\n");
embExitBad();
}
} while (ch != 'A' && ch != 'B');
if (ch == 'A') {
if (!(treenode[j - 1]->deleted) && !treenode[j - 1]->tip) {
changed = true;
copytree();
dnamove_re_move(&treenode[i - 1], &q);
add_child(treenode[j - 1], treenode[i - 1]);
if (fromtype == beforenode)
consolidatetree(q->index);
} else
ok2 = false;
} else {
if (j != root->index) { /* can't insert at root */
changed = true;
copytree();
dnamove_re_move(&treenode[i - 1], &q);
if (q != NULL) {
treenode[q->index-1]->next->back = treenode[i-1];
treenode[i-1]->back = treenode[q->index-1]->next;
}
add_before(treenode[j - 1], treenode[i - 1]);
} else
ok2 = false;
} /* endif (before or at node) */
} /* endif (ok to do move) */
} /* endif (destination node ok) */
} /* endif (from node ok) */
dnamove_printree();
if (!(ok1 && ok2))
printf("Not a possible rearrangement. Try again: \n");
else {
written = false;
}
} /* rearrange */
void dnamove_nextinc(void)
{
/* show next incompatible site */
long disp0;
boolean done;
display = true;
disp0 = dispchar;
done = false;
do {
dispchar++;
if (dispchar > chars) {
dispchar = 1;
done = (disp0 == 0);
}
} while (!(necsteps[dispchar - 1] != numsteps[dispchar - 1] ||
dispchar == disp0 || done));
dnamove_printree();
} /* dnamove_nextinc */
void dnamove_nextchar(void)
{
/* show next site */
display = true;
dispchar++;
if (dispchar > chars)
dispchar = 1;
dnamove_printree();
} /* dnamove_nextchar */
void dnamove_prevchar(void)
{
/* show previous site */
display = true;
dispchar--;
if (dispchar < 1)
dispchar = chars;
dnamove_printree();
} /* dnamove_prevchar */
void dnamove_show(void)
{
long i;
boolean ok;
do {
printf("SHOW: (Character number or 0 to see none)? ");
inpnum(&i, &ok);
ok = (ok && (i == 0 || (i >= 1 && i <= chars)));
if (ok && i != 0) {
display = true;
dispchar = i;
}
if (ok && i == 0)
display = false;
} while (!ok);
dnamove_printree();
} /* dnamove_show */
void tryadd(node *p, node **item, node **nufork, double *place)
{
/* temporarily adds one fork and one tip to the tree.
Records scores in ARRAY place */
dnamove_add(p, *item, *nufork);
evaluate(root);
place[p->index - 1] = -like;
dnamove_re_move(item, nufork);
} /* tryadd */
void addpreorder(node *p, node *item_, node *nufork_, double *place)
{
/* traverses a binary tree, calling PROCEDURE tryadd
at a node before calling tryadd at its descendants */
node *item, *nufork, *q;
item = item_;
nufork = nufork_;
if (p == NULL)
return;
tryadd(p,&item,&nufork,place);
if (!p->tip) {
q = p->next;
do {
addpreorder(q->back, item,nufork,place);
q = q->next;
} while (q != p);
}
} /* addpreorder */
void try(void)
{
/* Remove node, try it in all possible places */
double *place;
long i, j, oldcompat, saveparent;
double current;
node *q, *dummy, *rute;
boolean tied, better, ok, madenode;
madenode = false;
printf("Try other positions for which node? ");
inpnum(&i, &ok);
if (!(ok && i >= 1 && i <= nonodes && i != root->index)) {
printf("Not a possible choice! ");
return;
}
copytree();
printf("WAIT ...\n");
place = (double *)Malloc(nonodes*sizeof(double));
for (j = 0; j < (nonodes); j++)
place[j] = -1.0;
evaluate(root);
current = -like;
oldcompat = compatible;
what = i;
/* q = ring base of i's parent */
q = treenode[treenode[i - 1]->back->index - 1];
saveparent = q->index;
/* if i is a left child, fromwhere = index of right sibling (binary) */
/* if i is a right child, fromwhere = index of left sibling (binary) */
if (q->next->back->index == i)
fromwhere = q->next->next->back->index;
else
fromwhere = q->next->back->index;
rute = root;
/* if root is i's parent ... */
if (q->next->next->next == q) {
if (root == treenode[treenode[i - 1]->back->index - 1]) {
/* if i is left child then rute becomes right child,
and vice-versa */
if (treenode[treenode[i - 1]->back->index - 1]->next->back == treenode[i - 1])
rute = treenode[treenode[i - 1]->back->index - 1]->next->next->back;
else
rute = treenode[treenode[i - 1]->back->index - 1]->next->back;
}
}
/* Remove i and perhaps its parent node from the tree. If i is part of a
multifurcation, *dummy will come back null. If so, make a new internal
node to be i's parent as it is inserted in various places around the
tree.
*/
dnamove_re_move(&treenode[i - 1], &dummy);
if (dummy == NULL) {
madenode = true;
nonodes++;
maketriad(&dummy, nonodes);
}
oldleft = wasleft;
root = rute;
addpreorder(root, treenode[i - 1], dummy, place);
wasleft = oldleft;
restoring = true;
if (madenode) {
add_child(treenode[saveparent - 1], treenode[i - 1]);
nonodes--;
} else
dnamove_add(treenode[fromwhere - 1], treenode[what - 1], q);
like = -current;
compatible = oldcompat;
restoring = false;
better = false;
printf(" BETTER: ");
for (j = 1; j <= (nonodes); j++) {
if (place[j - 1] < current && place[j - 1] >= 0.0) {
printf("%3ld:%6.2f", j, place[j - 1]);
better = true;
}
}
if (!better)
printf(" NONE");
printf("\n TIED: ");
tied = false;
for (j = 1; j <= (nonodes); j++) {
if (fabs(place[j - 1] - current) < 1.0e-6 && j != fromwhere) {
if (j < 10)
printf("%2ld", j);
else
printf("%3ld", j);
tied = true;
}
}
if (tied)
printf(":%6.2f\n", current);
else
printf("NONE\n");
changed = true;
free(place);
} /* try */
void undo(void)
{
boolean btemp;
/* don't undo to an uninitialized tree */
if (!treesets[othertree].initialized) {
dnamove_printree();
printf("Nothing to undo.\n");
return;
}
treesets[whichtree].root = root;
treesets[whichtree].treenode = treenode;
treesets[whichtree].nonodes = nonodes;
treesets[whichtree].waswritten = waswritten;
treesets[whichtree].initialized = true;
whichtree = othertree;
root = treesets[whichtree].root;
treenode = treesets[whichtree].treenode;
nonodes = treesets[whichtree].nonodes;
waswritten = treesets[whichtree].waswritten;
if (othertree == 0)
othertree = 1;
else
othertree = 0;
changed = true;
dnamove_printree();
btemp = oldwritten;
oldwritten = written;
written = btemp;
} /* undo */
void treewrite(boolean done)
{
/* write out tree to a file */
//treeoptions(waswritten, &ch, &outtree, outtreename, progname);
if (!done)
dnamove_printree();
if (waswritten && ch != 'A' && ch != 'R')
return;
col = 0;
treeout(root, 1, &col, root);
printf("\nTree written to file \"%s\"\n\n", outtreename);
waswritten = true;
written = true;
FClose(outtree);
#ifdef MAC
fixmacfile(outtreename);
#endif
}
/* treewrite */
void clade(void)
{
/* pick a subtree and show only that on screen */
long i;
boolean ok;
printf("Select subtree rooted at which node (0 for whole tree)? ");
inpnum(&i, &ok);
ok = (ok && ((unsigned)i) <= ((unsigned)nonodes));
if (ok) {
subtree = (i > 0);
if (subtree)
nuroot = treenode[i - 1];
else
nuroot = root;
}
dnamove_printree();
if (!ok)
printf("Not possible to use this node. ");
} /* clade */
void fliptrav(node *p, boolean recurse)
{
node *q, *temp, *r =NULL, *rprev =NULL, *l, *lprev;
boolean lprevflag;
int nodecount, loopcount, i;
if (p->tip)
return;
q = p->next;
l = q;
lprev = p;
nodecount = 0;
do {
nodecount++;
if (q->next->next == p) {
rprev = q;
r = q->next;
}
q = q->next;
} while (p != q);
if (nodecount == 1)
return;
loopcount = nodecount / 2;
for (i=0; inext = r;
rprev->next = l;
temp = r->next;
r->next = l->next;
l->next = temp;
if (i < (loopcount - 1)) {
lprevflag = false;
q = p->next;
do {
if (q == lprev->next && !lprevflag) {
lprev = q;
l = q->next;
lprevflag = true;
}
if (q->next == rprev) {
rprev = q;
r = q->next;
}
q = q->next;
} while (p != q);
}
}
if (recurse) {
q = p->next;
do {
fliptrav(q->back, true);
q = q->next;
} while (p != q);
}
} /* fliptrav */
void flip(long atnode)
{
/* flip at a node left-right */
long i;
boolean ok;
if (atnode == 0) {
printf("Flip branches at which node? ");
inpnum(&i, &ok);
ok = (ok && i > spp && i <= nonodes);
} else {
i = atnode;
ok = true;
}
if (ok) {
copytree();
fliptrav(treenode[i - 1], true);
}
if (atnode == 0)
dnamove_printree();
if (ok) {
written = false;
return;
}
if ((i >= 1 && i <= spp) ||
(i > spp && i <= nonodes))
printf("Can't flip there. ");
else
printf("No such node. ");
} /* flip */
void changeoutgroup(void)
{
long i;
boolean ok;
oldoutgrno = outgrno;
do {
printf("Which node should be the new outgroup? ");
inpnum(&i, &ok);
ok = (ok && i >= 1 && i <= nonodes &&
i != root->index);
if (ok)
outgrno = i;
} while (!ok);
copytree();
dnamove_reroot(treenode[outgrno - 1]);
changed = true;
lastop = reroott;
dnamove_printree();
oldwritten = written;
written = false;
} /* changeoutgroup */
void redisplay(void)
{
boolean done = false;
waswritten = false;
do {
fprintf(stderr, "NEXT (R # + - S . T U W O F H J K L C ? X Q) ");
fprintf(stderr, "(? for Help): ");
#ifdef WIN32
phyFillScreenColor();
#endif
fflush(stdout);
scanf("%c%*[^\n]", &ch);
getchar();
uppercase(&ch);
if (strchr("HJKLCFORSTUXQ+#-.W?",ch) != NULL){
switch (ch) {
case 'R':
rearrange();
break;
case '#':
dnamove_nextinc();
break;
case '+':
dnamove_nextchar();
break;
case '-':
dnamove_prevchar();
break;
case 'S':
dnamove_show();
break;
case '.':
dnamove_printree();
break;
case 'T':
try();
break;
case 'U':
undo();
break;
case 'W':
treewrite(done);
break;
case 'O':
changeoutgroup();
break;
case 'F':
flip(0);
break;
case 'H':
window(left, &leftedge, &topedge, hscroll, vscroll, treelines,
screenlines, screenwidth, farthest, subtree);
dnamove_printree();
break;
case 'J':
window(downn, &leftedge, &topedge, hscroll, vscroll, treelines,
screenlines, screenwidth, farthest, subtree);
dnamove_printree();
break;
case 'K':
window(upp, &leftedge, &topedge, hscroll, vscroll, treelines,
screenlines, screenwidth, farthest, subtree);
dnamove_printree();
break;
case 'L':
window(right, &leftedge, &topedge, hscroll, vscroll, treelines,
screenlines, screenwidth, farthest, subtree);
dnamove_printree();
break;
case 'C':
clade();
break;
case '?':
help("site");
dnamove_printree();
break;
case 'X':
done = true;
break;
case 'Q':
done = true;
break;
}
}
} while (!done);
if (written)
return;
do {
fprintf(stderr, "Do you want to write out the tree to a file? (Y or N): ");
#ifdef WIN32
phyFillScreenColor();
#endif
fflush(stdout);
scanf("%c%*[^\n]", &ch);
getchar();
if (ch == 'Y' || ch == 'y')
treewrite(done);
} while (ch != 'Y' && ch != 'y' && ch != 'N' && ch != 'n');
} /* redisplay */
void treeconstruct(void)
{
/* constructs a binary tree from the pointers in treenode. */
int i;
restoring = false;
subtree = false;
display = false;
dispchar = 0;
earlytree = true;
waswritten = false;
buildtree();
/* get an accurate value for nonodes by finding out where the nodes
really stop
*/
for (i=0;i