# Path: phydmslib/constants.py
# ALMOST_ZERO = 1.0e-6
# 
# CODON_TO_INDEX = {}
# 
# N_CODON = len(CODON_TO_INDEX)


import copy
import warnings
import numpy
import scipy.optimize
import Bio.Phylo
import phydmslib.models
    import doctest
from phydmslib.numutils import broadcastMatrixVectorMultiply
from phydmslib.constants import ALMOST_ZERO, CODON_TO_INDEX, N_CODON
                converged = True

        return '\n'.join(summary)

    @property
    def tree(self):
        """Tree with branch lengths in codon substitutions per site.

        The tree is a `Bio.Phylo.BaseTree.Tree` object.

        This is the current tree after whatever optimizations have
        been performed so far.
        """
        bs = self.model.branchScale
        for node in self._tree.find_clades():
            if node != self._tree.root:
                node.branch_length = self.t[self.name_to_nodeindex[node]] * bs
        return self._tree

    @property
    def paramsarraybounds(self):
        """Bounds for parameters in `paramsarray`."""
        bounds = []
        for (_i, param) in self._index_to_param.items():
            if isinstance(param, str):
                bounds.append(self.model.PARAMLIMITS[param])
            elif isinstance(param, tuple):
                bounds.append(self.model.PARAMLIMITS[param[0]])
            else:
                raise ValueError("Invalid param type")

# Path: phydmslib/constants.py
# ALMOST_ZERO = 1.0e-6
# 
# CODON_TO_INDEX = {}
# 
# N_CODON = len(CODON_TO_INDEX)


# Path: phydmslib/treelikelihood.py
import copy
import warnings
import numpy
import scipy.optimize
import Bio.Phylo
import phydmslib.models
    import doctest
from phydmslib.numutils import broadcastMatrixVectorMultiply
from phydmslib.constants import ALMOST_ZERO, CODON_TO_INDEX, N_CODON

                converged = True

        return '\n'.join(summary)

    @property
    def tree(self):
        """Tree with branch lengths in codon substitutions per site.

        The tree is a `Bio.Phylo.BaseTree.Tree` object.

        This is the current tree after whatever optimizations have
        been performed so far.
        """
        bs = self.model.branchScale
        for node in self._tree.find_clades():
            if node != self._tree.root:
                node.branch_length = self.t[self.name_to_nodeindex[node]] * bs
        return self._tree

    @property
    def paramsarraybounds(self):
        """Bounds for parameters in `paramsarray`."""
        bounds = []
        for (_i, param) in self._index_to_param.items():
            if isinstance(param, str):
                bounds.append(self.model.PARAMLIMITS[param])
            elif isinstance(param, tuple):
                bounds.append(self.model.PARAMLIMITS[param[0]])
            else:
                raise ValueError("Invalid param type")

        bounds = [(tup[0] + ALMOST_ZERO, tup[1] - ALMOST_ZERO)