def optimal_reroot(self, force_positive=True, slope=None):

best_root = self.find_best_root(force_positive=force_positive, slope=slope)<EOL>best_node = best_root["<STR_LIT>"]<EOL>x = best_root["<STR_LIT>"]<EOL>if x<<NUM_LIT>:<EOL><INDENT>new_node = best_node<EOL><DEDENT>elif x><NUM_LIT:1.0>-<NUM_LIT>:<EOL><INDENT>new_node = best_node.up<EOL><DEDENT>else:<EOL><INDENT>new_node = Phylo.BaseTree.Clade()<EOL>new_node.branch_length = best_node.branch_length*(<NUM_LIT:1>-x)<EOL>new_node.up = best_node.up<EOL>new_node.clades = [best_node]<EOL>new_node.up.clades = [k if k!=best_node else new_node<EOL>for k in best_node.up.clades]<EOL>best_node.branch_length *= x<EOL>best_node.up = new_node<EOL><DEDENT>new_node.rtt_regression = best_root<EOL>self.tree.root_with_outgroup(new_node)<EOL>self.tree.ladderize()<EOL>for n in self.tree.get_nonterminals(order='<STR_LIT>'):<EOL><INDENT>for c in n:<EOL><INDENT>c.up=n<EOL><DEDENT><DEDENT>return best_root<EOL>

determine the best root and reroot the tree to this value.
Note that this can change the parent child relations of the tree
and values associated with branches rather than nodes
(e.g. confidence) might need to be re-evaluated afterwards

Parameters
----------
force_positive : bool, optional
    if True, the search for a root will only consider positive rate estimates

slope : float, optional
    if given, it will find the optimal root given a fixed rate. If slope==0, this
    corresponds to minimal root-to-tip variance rooting (min_dev)

Returns
-------
dict
    regression parameters


def clock_plot(self, add_internal=False, ax=None, regression=None,<EOL>confidence=True, n_sigma = <NUM_LIT:2>, fs=<NUM_LIT>):

import matplotlib.pyplot as plt<EOL>if ax is None:<EOL><INDENT>plt.figure()<EOL>ax=plt.subplot(<NUM_LIT>)<EOL><DEDENT>self.tree.root._v=<NUM_LIT:0><EOL>for n in self.tree.get_nonterminals(order='<STR_LIT>'):<EOL><INDENT>for c in n:<EOL><INDENT>c._v = n._v + self.branch_value(c)<EOL><DEDENT><DEDENT>tips = self.tree.get_terminals()<EOL>internal = self.tree.get_nonterminals()<EOL>xi = np.array([self.tip_value(n) for n in tips])<EOL>yi = np.array([n._v for n in tips])<EOL>ind = np.array([n.bad_branch  if hasattr(n, '<STR_LIT>') else False for n in tips])<EOL>if add_internal:<EOL><INDENT>xi_int = np.array([n.numdate for n in internal])<EOL>yi_int = np.array([n._v for n in internal])<EOL>ind_int = np.array([n.bad_branch  if hasattr(n, '<STR_LIT>') else False  for n in internal])<EOL><DEDENT>if regression:<EOL><INDENT>t_mrca = -regression['<STR_LIT>']/regression['<STR_LIT>']<EOL>if add_internal:<EOL><INDENT>time_span = np.max(xi_int[~ind_int]) - np.min(xi_int[~ind_int])<EOL>x_vals = np.array([max(np.min(xi_int[~ind_int]), t_mrca) - <NUM_LIT:0.1>*time_span, np.max(xi[~ind])+<NUM_LIT>*time_span])<EOL><DEDENT>else:<EOL><INDENT>time_span = np.max(xi[~ind]) - np.min(xi[~ind])<EOL>x_vals = np.array([max(np.min(xi[~ind]), t_mrca) - <NUM_LIT:0.1>*time_span, np.max(xi[~ind]+<NUM_LIT>*time_span)])<EOL><DEDENT>if confidence and '<STR_LIT>' in regression:<EOL><INDENT>x_vals = np.linspace(x_vals[<NUM_LIT:0>], x_vals[<NUM_LIT:1>], <NUM_LIT:100>)<EOL>y_vals = regression['<STR_LIT>']*x_vals + regression['<STR_LIT>']<EOL>dev = n_sigma*np.array([np.sqrt(regression['<STR_LIT>'][:<NUM_LIT:2>,:<NUM_LIT:2>].dot(np.array([x, <NUM_LIT:1>])).dot(np.array([x,<NUM_LIT:1>]))) for x in x_vals])<EOL>dev_slope = n_sigma*np.sqrt(regression['<STR_LIT>'][<NUM_LIT:0>,<NUM_LIT:0>])<EOL>ax.fill_between(x_vals, y_vals-dev, y_vals+dev, alpha=<NUM_LIT>)<EOL>dp = np.array([regression['<STR_LIT>']/regression['<STR_LIT>']**<NUM_LIT:2>,-<NUM_LIT:1.>/regression['<STR_LIT>']])<EOL>dev_rtt = n_sigma*np.sqrt(regression['<STR_LIT>'][:<NUM_LIT:2>,:<NUM_LIT:2>].dot(dp).dot(dp))<EOL><DEDENT>else:<EOL><INDENT>dev_rtt = None<EOL>dev_slope = None<EOL><DEDENT>ax.plot(x_vals, regression['<STR_LIT>']*x_vals + regression['<STR_LIT>'],<EOL>label = r"<STR_LIT>"+"<STR_LIT:\n>"+<EOL>r"<STR_LIT>"%(regression["<STR_LIT>"])<EOL>+ ("<STR_LIT>"%dev_slope if dev_slope else "<STR_LIT>") +<EOL>"<STR_LIT>"%(-regression['<STR_LIT>']/regression['<STR_LIT>']) +<EOL>("<STR_LIT>"%dev_rtt if dev_rtt else "<STR_LIT>"))<EOL><DEDENT>ax.scatter(xi[~ind], yi[~ind], label=("<STR_LIT>" if add_internal else None))<EOL>if ind.sum():<EOL><INDENT>try:<EOL><INDENT>tmp_x = np.array([np.mean(n.raw_date_constraint) if n.raw_date_constraint else None<EOL>for n in self.tree.get_terminals()])<EOL>ax.scatter(tmp_x[ind], yi[ind], label="<STR_LIT>", c='<STR_LIT:r>')<EOL><DEDENT>except:<EOL><INDENT>pass<EOL><DEDENT><DEDENT>if add_internal:<EOL><INDENT>ax.scatter(xi_int[~ind_int], yi_int[~ind_int], label="<STR_LIT>")<EOL><DEDENT>ax.set_ylabel('<STR_LIT>', fontsize=fs)<EOL>ax.set_xlabel('<STR_LIT:date>', fontsize=fs)<EOL>ax.ticklabel_format(useOffset=False)<EOL>ax.tick_params(labelsize=fs*<NUM_LIT>)<EOL>ax.set_ylim([<NUM_LIT:0>, <NUM_LIT>*np.max(yi)])<EOL>plt.tight_layout()<EOL>plt.legend(fontsize=fs*<NUM_LIT>)<EOL>

Plot root-to-tip distance vs time as a basic time-tree diagnostic

        Parameters
        ----------
        add_internal : bool, optional
            add internal nodes. this will only work if the tree has been dated already
        ax : None, optional
            an matplotlib axis to plot into. if non provided, a new figure is opened
        regression : None, optional
            a dict containing parameters of a root-to-tip vs time regression as
            returned by the function base_regression
        confidence : bool, optional
            add confidence area to the regression line
        n_sigma : int, optional
            number of standard deviations for the confidence area.
        fs : int, optional
            fontsize


try:<EOL><INDENT>return interp_object.x[interp_object(interp_object.x).argmin()]<EOL><DEDENT>except Exception as e:<EOL><INDENT>s = "<STR_LIT>" + str(interp_object.x) +"<STR_LIT>" + str(interp_object.x.min()) + "<STR_LIT>" + str(interp_object.x.max())<EOL>raise e<EOL><DEDENT>

Find the global minimum of a function represented as an interpolation object.


new_grid = np.sort(np.concatenate([interp_object.x[:-<NUM_LIT:1>] + <NUM_LIT:0.1>*ii*np.diff(interp_object.x)<EOL>for ii in range(<NUM_LIT:10>)]).flatten())<EOL>tmp_prop = np.exp(-(interp_object(new_grid)-interp_object.y.min()))<EOL>tmp_cumsum = np.cumsum(<NUM_LIT:0.5>*(tmp_prop[<NUM_LIT:1>:]+tmp_prop[:-<NUM_LIT:1>])*np.diff(new_grid))<EOL>median_index = min(len(tmp_cumsum)-<NUM_LIT:3>, max(<NUM_LIT:2>,np.searchsorted(tmp_cumsum, tmp_cumsum[-<NUM_LIT:1>]*<NUM_LIT:0.5>)+<NUM_LIT:1>))<EOL>return new_grid[median_index]<EOL>

Find the median of the function represented as an interpolation object.


if dt is None:<EOL><INDENT>dt = datetime.datetime.now()<EOL><DEDENT>try:<EOL><INDENT>res = dt.year + dt.timetuple().tm_yday / <NUM_LIT><EOL><DEDENT>except:<EOL><INDENT>res = None<EOL><DEDENT>return res<EOL>

Convert datetime object to the numeric date.
The numeric date format is YYYY.F, where F is the fraction of the year passed

Parameters
----------
 dt:  datetime.datetime, None
    date of to be converted. if None, assume today


print("<STR_LIT>")<EOL>dates = {}<EOL>if not os.path.isfile(date_file):<EOL><INDENT>print("<STR_LIT>"%date_file)<EOL>return dates<EOL><DEDENT>full_sep = '<STR_LIT:\t>' if date_file.endswith('<STR_LIT>') else r'<STR_LIT>'<EOL>try:<EOL><INDENT>df = pd.read_csv(date_file, sep=full_sep, engine='<STR_LIT>')<EOL>potential_date_columns = []<EOL>potential_numdate_columns = []<EOL>potential_index_columns = []<EOL>for ci,col in enumerate(df.columns):<EOL><INDENT>d = df.iloc[<NUM_LIT:0>,ci]<EOL>if type(d)==str and d[<NUM_LIT:0>] in ['<STR_LIT:">', "<STR_LIT:'>"] and d[-<NUM_LIT:1>] in ['<STR_LIT:">', "<STR_LIT:'>"]:<EOL><INDENT>for i,tmp_d in enumerate(df.iloc[:,ci]):<EOL><INDENT>df.iloc[i,ci] = tmp_d.strip(d[<NUM_LIT:0>])<EOL><DEDENT><DEDENT>if '<STR_LIT:date>' in col.lower():<EOL><INDENT>potential_date_columns.append((ci, col))<EOL><DEDENT>if any([x==col.lower() for x in ['<STR_LIT:name>', '<STR_LIT>', '<STR_LIT>']]):<EOL><INDENT>potential_index_columns.append((ci, col))<EOL><DEDENT><DEDENT>dates = {}<EOL>if not len(potential_index_columns):<EOL><INDENT>print("<STR_LIT>"<EOL>"<STR_LIT>", file=sys.stderr)<EOL>return dates<EOL><DEDENT>else:<EOL><INDENT>index_col = sorted(potential_index_columns)[<NUM_LIT:0>][<NUM_LIT:1>]<EOL>print("<STR_LIT>"%index_col)<EOL><DEDENT>if len(potential_date_columns)>=<NUM_LIT:1>:<EOL><INDENT>idx = potential_date_columns[<NUM_LIT:0>][<NUM_LIT:0>]<EOL>col_name = potential_date_columns[<NUM_LIT:0>][<NUM_LIT:1>]<EOL>print("<STR_LIT>"%col_name)<EOL>for ri, row in df.iterrows():<EOL><INDENT>date_str = row.loc[col_name]<EOL>k = row.loc[index_col]<EOL>try:<EOL><INDENT>dates[k] = float(date_str)<EOL>continue<EOL><DEDENT>except ValueError:<EOL><INDENT>if date_str[<NUM_LIT:0>]=='<STR_LIT:[>' and date_str[-<NUM_LIT:1>]=='<STR_LIT:]>' and len(date_str[<NUM_LIT:1>:-<NUM_LIT:1>].split('<STR_LIT::>'))==<NUM_LIT:2>:<EOL><INDENT>try:<EOL><INDENT>dates[k] = [float(x) for x in date_str[<NUM_LIT:1>:-<NUM_LIT:1>].split('<STR_LIT::>')]<EOL>continue<EOL><DEDENT>except ValueError:<EOL><INDENT>pass<EOL><DEDENT><DEDENT>try:<EOL><INDENT>tmp_date = pd.to_datetime(date_str)<EOL>dates[k] = numeric_date(tmp_date)<EOL><DEDENT>except ValueError:  <EOL><INDENT>lower, upper = ambiguous_date_to_date_range(date_str, '<STR_LIT>')<EOL>if lower is not None:<EOL><INDENT>dates[k] = [numeric_date(x) for x in [lower, upper]]<EOL><DEDENT><DEDENT><DEDENT><DEDENT><DEDENT>else:<EOL><INDENT>print("<STR_LIT>", file=sys.stderr)<EOL><DEDENT>if all(v is None for v in dates.values()):<EOL><INDENT>print("<STR_LIT>", file=sys.stderr)<EOL>return {}<EOL><DEDENT>return dates<EOL><DEDENT>except:<EOL><INDENT>print("<STR_LIT>", file=sys.stderr)<EOL>return {}<EOL><DEDENT>

parse dates from the arguments and return a dictionary mapping
taxon names to numerical dates.

Parameters
----------
date_file : str
    name of file to parse meta data from

Returns
-------
dict
    dictionary linking fields in a column interpreted as taxon name
    (first column that contains 'name', 'strain', 'accession')
    to a numerical date inferred from a column that contains 'date'.
    It will first try to parse the column as float, than via
    pandas.to_datetime and finally as ambiguous date such as 2018-05-XX


def ambiguous_date_to_date_range(mydate, fmt="<STR_LIT>", min_max_year=None):

from datetime import datetime<EOL>sep = fmt.split('<STR_LIT:%>')[<NUM_LIT:1>][-<NUM_LIT:1>]<EOL>min_date, max_date = {}, {}<EOL>today = datetime.today().date()<EOL>for val, field  in zip(mydate.split(sep), fmt.split(sep+'<STR_LIT:%>')):<EOL><INDENT>f = '<STR_LIT>' if '<STR_LIT:y>' in field.lower() else ('<STR_LIT>' if '<STR_LIT:d>' in field.lower() else '<STR_LIT>')<EOL>if '<STR_LIT>' in val:<EOL><INDENT>if f=='<STR_LIT>':<EOL><INDENT>if min_max_year:<EOL><INDENT>min_date[f]=min_max_year[<NUM_LIT:0>]<EOL>if len(min_max_year)><NUM_LIT:1>:<EOL><INDENT>max_date[f]=min_max_year[<NUM_LIT:1>]<EOL><DEDENT>elif len(min_max_year)==<NUM_LIT:1>:<EOL><INDENT>max_date[f]=<NUM_LIT> <EOL><DEDENT><DEDENT>else:<EOL><INDENT>return None, None<EOL><DEDENT><DEDENT>elif f=='<STR_LIT>':<EOL><INDENT>min_date[f]=<NUM_LIT:1><EOL>max_date[f]=<NUM_LIT:12><EOL><DEDENT>elif f=='<STR_LIT>':<EOL><INDENT>min_date[f]=<NUM_LIT:1><EOL>max_date[f]=<NUM_LIT><EOL><DEDENT><DEDENT>else:<EOL><INDENT>try:<EOL><INDENT>min_date[f]=int(val)<EOL>max_date[f]=int(val)<EOL><DEDENT>except ValueError:<EOL><INDENT>print("<STR_LIT>"+mydate, file=sys.stderr)<EOL>return None, None<EOL><DEDENT><DEDENT><DEDENT>max_date['<STR_LIT>'] = min(max_date['<STR_LIT>'], <NUM_LIT> if max_date['<STR_LIT>'] in [<NUM_LIT:1>,<NUM_LIT:3>,<NUM_LIT:5>,<NUM_LIT:7>,<NUM_LIT:8>,<NUM_LIT:10>,<NUM_LIT:12>]<EOL>else <NUM_LIT> if max_date['<STR_LIT>']==<NUM_LIT:2> else <NUM_LIT:30>)<EOL>lower_bound = datetime(year=min_date['<STR_LIT>'], month=min_date['<STR_LIT>'], day=min_date['<STR_LIT>']).date()<EOL>upper_bound = datetime(year=max_date['<STR_LIT>'], month=max_date['<STR_LIT>'], day=max_date['<STR_LIT>']).date()<EOL>return (lower_bound, upper_bound if upper_bound<today else today)<EOL>

parse an abiguous date such as 2017-XX-XX to [2017,2017.999]

    Parameters
    ----------
    mydate : str
        date string to be parsed
    fmt : str
        format descriptor. default is %Y-%m-%d
    min_max_year : None, optional
        if date is completely unknown, use this as bounds.

    Returns
    -------
    tuple
        upper and lower bounds on the date. return (None, None) if errors


dc = cls()<EOL>dc.clock_rate = clock_model['<STR_LIT>']<EOL>dc.intercept = clock_model['<STR_LIT>']<EOL>dc.chisq = clock_model['<STR_LIT>'] if '<STR_LIT>' in clock_model else None<EOL>dc.valid_confidence = clock_model['<STR_LIT>'] if '<STR_LIT>' in clock_model else False<EOL>if '<STR_LIT>' in clock_model and dc.valid_confidence:<EOL><INDENT>dc.cov = clock_model['<STR_LIT>']<EOL><DEDENT>dc.r_val = clock_model['<STR_LIT>']<EOL>return dc<EOL>

Create the conversion object automatically from the tree

Parameters
----------

 clock_model : dict
    dictionary as returned from TreeRegression with fields intercept and slope


return abs(date1 - date2) * self.clock_rate<EOL>

Compute branch length given the dates of the two nodes.

Parameters
-----------

 date1 : int
    date of the first node (days before present)

 date2 : int
    date of the second node (days before present)

Returns:
--------

 branch length : double
    Branch length, assuming that the dependence
    between the node date and the node depth in the the tree is linear.


return (numeric_date() - numdate) * abs(self.clock_rate)<EOL>

Convert the numeric date to the branch-len scale


return abs_t / abs(self.clock_rate)<EOL>

Convert the time before present measured in branch length units to years


return numeric_date() - self.to_years(tbp)<EOL>


return (d2r-self.intercept)/self.clock_rate<EOL>

estimate the numerical date based on the distance to root.
-> crude dating of internal nodes


def JC69 (mu=<NUM_LIT:1.0>, alphabet="<STR_LIT>", **kwargs):

num_chars = len(alphabets[alphabet])<EOL>W, pi = np.ones((num_chars,num_chars)), np.ones(num_chars)<EOL>gtr = GTR(alphabet=alphabet)<EOL>gtr.assign_rates(mu=mu, pi=pi, W=W)<EOL>return gtr<EOL>

Jukes-Cantor 1969 model. This model assumes equal concentrations
of the nucleotides and equal transition rates between nucleotide states.
For more info, see: Jukes and Cantor (1969). Evolution of Protein Molecules.
                    New York: Academic Press. pp. 21–132

Parameters
-----------

 mu : float
    substitution rate

 alphabet : str
    specify alphabet to use.
    Available alphabets are:

     'nuc' - nucleotides only, gaps ignored

     'nuc_gap' - nucleotide alphabet with gaps, gaps can be ignored optionally


def K80(mu=<NUM_LIT:1.>, kappa=<NUM_LIT:0.1>, **kwargs):

num_chars = len(alphabets['<STR_LIT>'])<EOL>pi = np.ones(len(alphabets['<STR_LIT>']), dtype=float)/len(alphabets['<STR_LIT>'])<EOL>W = _create_transversion_transition_W(kappa)<EOL>gtr = GTR(alphabet=alphabets['<STR_LIT>'])<EOL>gtr.assign_rates(mu=mu, pi=pi, W=W)<EOL>return gtr<EOL>

Kimura 1980 model. Assumes equal concentrations across nucleotides, but
allows different rates between transitions and transversions. The ratio
of the transversion/transition rates is given by kappa parameter.
For more info, see
Kimura (1980),  J. Mol. Evol. 16 (2): 111–120. doi:10.1007/BF01731581.

Current implementation of the model does not account for the gaps.

Parameters
-----------

 mu : float
    Overall substitution rate

 kappa : float
    Ratio of transversion/transition rates


def F81(mu=<NUM_LIT:1.0>, pi=None, alphabet="<STR_LIT>", **kwargs):

if pi is None:<EOL><INDENT>pi=<NUM_LIT>*np.ones(<NUM_LIT:4>, dtype=float)<EOL><DEDENT>num_chars = len(alphabets[alphabet])<EOL>pi = np.array(pi, dtype=float)<EOL>if num_chars != len(pi) :<EOL><INDENT>pi = np.ones((num_chars, ), dtype=float)<EOL>print ("<STR_LIT>"<EOL>"<STR_LIT>")<EOL><DEDENT>W = np.ones((num_chars,num_chars))<EOL>pi /= (<NUM_LIT:1.0> * np.sum(pi))<EOL>gtr = GTR(alphabet=alphabets[alphabet])<EOL>gtr.assign_rates(mu=mu, pi=pi, W=W)<EOL>return gtr<EOL>

Felsenstein 1981 model. Assumes non-equal concentrations across nucleotides,
but the transition rate between all states is assumed to be equal. See
Felsenstein (1981), J. Mol. Evol. 17  (6): 368–376. doi:10.1007/BF01734359
for details.

Current implementation of the model does not account for the gaps (treatment of
gaps as characters is possible if specify alphabet='nuc_gap').

Parameters
-----------

 mu : float
    Substitution rate

 pi : numpy.array
    Nucleotide concentrations

 alphabet : str
    Alphabet to use. POsiible values are: ['nuc', 'nuc_gap'] Default 'nuc', which discounts al gaps.
    'nuc_gap' alphabet enables treatmen of gaps as characters.


def HKY85(mu=<NUM_LIT:1.0>, pi=None, kappa=<NUM_LIT:0.1>, **kwargs):

if pi is None:<EOL><INDENT>pi=<NUM_LIT>*np.ones(<NUM_LIT:4>, dtype=float)<EOL><DEDENT>num_chars = len(alphabets['<STR_LIT>'])<EOL>if num_chars != pi.shape[<NUM_LIT:0>] :<EOL><INDENT>pi = np.ones((num_chars, ), dtype=float)<EOL>print ("<STR_LIT>"<EOL>"<STR_LIT>")<EOL><DEDENT>W = _create_transversion_transition_W(kappa)<EOL>pi /= pi.sum()<EOL>gtr = GTR(alphabet=alphabets['<STR_LIT>'])<EOL>gtr.assign_rates(mu=mu, pi=pi, W=W)<EOL>return gtr<EOL>

Hasegawa, Kishino and Yano 1985 model. Allows different concentrations of the
nucleotides (as in F81) + distinguishes between transition/transversionsubstitutions
(similar to K80). Link:
Hasegawa, Kishino, Yano (1985), J. Mol. Evol. 22 (2): 160–174. doi:10.1007/BF02101694

Current implementation of the model does not account for the gaps

Parameters
-----------

 mu : float
    Substitution rate

 pi : numpy.array
    Nucleotide concentrations

 kappa : float
    Ratio of transversion/transition substitution rates


def T92(mu=<NUM_LIT:1.0>, pi_GC=<NUM_LIT:0.5>, kappa=<NUM_LIT:0.1>, **kwargs):

W = _create_transversion_transition_W(kappa)<EOL>if pi_CG >=<NUM_LIT:1.>:<EOL><INDENT>raise ValueError("<STR_LIT>")<EOL><DEDENT>pi = np.array([(<NUM_LIT:1.>-pi_CG)*<NUM_LIT:0.5>, pi_CG*<NUM_LIT:0.5>, pi_CG*<NUM_LIT:0.5>, (<NUM_LIT:1>-pi_CG)*<NUM_LIT:0.5>])<EOL>gtr = GTR(alphabet=alphabets['<STR_LIT>'])<EOL>gtr.assign_rates(mu=mu, pi=pi, W=W)<EOL>return gtr<EOL>

Tamura 1992 model. Extending Kimura  (1980) model for the case where a
G+C-content bias exists. Link:
Tamura K (1992),  Mol.  Biol. Evol. 9 (4): 678–687.  DOI: 10.1093/oxfordjournals.molbev.a040752

Current implementation of the model does not account for the gaps

Parameters
-----------

 mu : float
    substitution rate

 pi_GC : float
    relative GC content

 kappa : float
    relative transversion/transition rate


def TN93(mu=<NUM_LIT:1.0>, kappa1=<NUM_LIT:1.>, kappa2=<NUM_LIT:1.>, pi=None, **kwargs):

if pi is None:<EOL><INDENT>pi=<NUM_LIT>*np.ones(<NUM_LIT:4>, dtype=float)<EOL><DEDENT>W = np.ones((<NUM_LIT:4>,<NUM_LIT:4>))<EOL>W = np.array([<EOL>[<NUM_LIT:1>,      kappa1, <NUM_LIT:1>,      kappa1],<EOL>[kappa1, <NUM_LIT:1>,      kappa1, kappa2],<EOL>[<NUM_LIT:1>,      kappa1, <NUM_LIT:1>,      kappa1],<EOL>[kappa1, kappa2, kappa1,  <NUM_LIT:1>]], dtype=float)<EOL>pi /=pi.sum()<EOL>num_chars = len(alphabets['<STR_LIT>'])<EOL>if num_chars != pi.shape[<NUM_LIT:0>] :<EOL><INDENT>pi = np.ones((num_chars, ), dtype=float)<EOL>print ("<STR_LIT>"<EOL>"<STR_LIT>")<EOL><DEDENT>gtr = GTR(alphabet=alphabets['<STR_LIT>'])<EOL>gtr.assign_rates(mu=mu, pi=pi, W=W)<EOL>return gtr<EOL>

Tamura and Nei 1993. The model distinguishes between the two different types of
transition: (A <-> G) is allowed to have a different rate to (C<->T).
Transversions have the same rate. The frequencies of the nucleotides are allowed
to be different. Link:
Tamura, Nei (1993), MolBiol Evol. 10 (3): 512–526. DOI:10.1093/oxfordjournals.molbev.a040023

Parameters
-----------

 mu : float
    Substitution rate

 kappa1 : float
    relative A<-->C, A<-->T, T<-->G and G<-->C rates

 kappa2 : float
    relative C<-->T rate

Note
----

 Rate of A<-->G substitution is set to one. All other rates (kappa1, kappa2)
are specified relative to this rate


W = np.ones((<NUM_LIT:4>,<NUM_LIT:4>))<EOL>W[<NUM_LIT:0>, <NUM_LIT:2>]=W[<NUM_LIT:1>, <NUM_LIT:3>]=W[<NUM_LIT:2>, <NUM_LIT:0>]=W[<NUM_LIT:3>,<NUM_LIT:1>]=kappa<EOL>return W<EOL>


def __init__(self, alphabet='<STR_LIT>', prof_map=None, logger=None):

self.debug=False<EOL>if isinstance(alphabet, str):<EOL><INDENT>if alphabet not in alphabet_synonyms:<EOL><INDENT>raise AttributeError("<STR_LIT>")<EOL><DEDENT>else:<EOL><INDENT>tmp_alphabet = alphabet_synonyms[alphabet]<EOL>self.alphabet = alphabets[tmp_alphabet]<EOL>self.profile_map = profile_maps[tmp_alphabet]<EOL><DEDENT><DEDENT>else:<EOL><INDENT>self.alphabet = alphabet<EOL>if prof_map is None: <EOL><INDENT>self.profile_map = {s:x for s,x in zip(self.alphabet, np.eye(len(self.alphabet)))}<EOL><DEDENT>else:<EOL><INDENT>self.profile_map = prof_map<EOL><DEDENT><DEDENT>if logger is None:<EOL><INDENT>def logger_default(*args,**kwargs):<EOL><INDENT>"""<STR_LIT>"""<EOL>if self.debug:<EOL><INDENT>print(*args)<EOL><DEDENT><DEDENT>self.logger = logger_default<EOL><DEDENT>else:<EOL><INDENT>self.logger = logger<EOL><DEDENT>self.ambiguous = None<EOL>self.gap_index = None<EOL>self.n_states = len(self.alphabet)<EOL>self.assign_gap_and_ambiguous()<EOL>tmp_rng_state = np.random.get_state()<EOL>np.random.seed(<NUM_LIT>)<EOL>self.break_degen = np.random.random(size=(self.n_states, self.n_states))*<NUM_LIT><EOL>np.random.set_state(tmp_rng_state)<EOL>self.logger("<STR_LIT>", <NUM_LIT:3>)<EOL>self.v = None <EOL>self.v_inv = None <EOL>self.eigenvals =None <EOL>self.assign_rates()<EOL>

Initialize empty evolutionary model.

Parameters
----------

 alphabet : str, numpy.array
    Alphabet of the sequence. If a string is passed, it is understood as
    an alphabet name. In this case, the alphabet and its profile map are pulled
    from :py:obj:`treetime.seq_utils`.

    If a numpy array of characters is passed, a new alphabet is constructed,
    and the default profile map is atached to it.

 prof_map : dict
    Dictionary linking characters in the sequence to the likelihood
    of observing characters in the alphabet. This is used to
    implement ambiguous characters like 'N'=[1,1,1,1] which are
    equally likely to be any of the 4 nucleotides. Standard profile_maps
    are defined in file seq_utils.py. If None is provided, no ambigous
    characters are supported.

 logger : callable
    Custom logging function that should take arguments (msg, level, warn=False),
    where msg is a string and level an integer to be compared against verbose.


return (self.W*self.Pi).T<EOL>

function that return the product of the transition matrix
           and the equilibrium frequencies to obtain the rate matrix
           of the GTR model


multi_site = len(self.Pi.shape)==<NUM_LIT:2><EOL>if multi_site:<EOL><INDENT>eq_freq_str = "<STR_LIT>"+str(np.round(self.average_rate,<NUM_LIT:6>))+'<STR_LIT:\n>'<EOL><DEDENT>else:<EOL><INDENT>eq_freq_str = "<STR_LIT>"+str(np.round(self.mu,<NUM_LIT:6>))+'<STR_LIT:\n>'<EOL><DEDENT>if not multi_site:<EOL><INDENT>eq_freq_str += "<STR_LIT>"<EOL>for a,p in zip(self.alphabet, self.Pi):<EOL><INDENT>eq_freq_str+='<STR_LIT:U+0020>'+str(a)+'<STR_LIT>'+str(np.round(p,<NUM_LIT:4>))+'<STR_LIT:\n>'<EOL><DEDENT><DEDENT>W_str = "<STR_LIT>"<EOL>W_str+='<STR_LIT:\t>'+'<STR_LIT:\t>'.join(map(str, self.alphabet))+'<STR_LIT:\n>'<EOL>for a,Wi in zip(self.alphabet, self.W):<EOL><INDENT>W_str+= '<STR_LIT:U+0020>'+str(a)+'<STR_LIT:\t>'+'<STR_LIT:\t>'.join([str(np.round(max(<NUM_LIT:0>,p),<NUM_LIT:4>)) for p in Wi])+'<STR_LIT:\n>'<EOL><DEDENT>if not multi_site:<EOL><INDENT>Q_str = "<STR_LIT>"<EOL>Q_str+='<STR_LIT:\t>'+'<STR_LIT:\t>'.join(map(str, self.alphabet))+'<STR_LIT:\n>'<EOL>for a,Qi in zip(self.alphabet, self.Q):<EOL><INDENT>Q_str+= '<STR_LIT:U+0020>'+str(a)+'<STR_LIT:\t>'+'<STR_LIT:\t>'.join([str(np.round(max(<NUM_LIT:0>,p),<NUM_LIT:4>)) for p in Qi])+'<STR_LIT:\n>'<EOL><DEDENT><DEDENT>return eq_freq_str + W_str + Q_str<EOL>

String representation of the GTR model for pretty printing


def assign_rates(self, mu=<NUM_LIT:1.0>, pi=None, W=None):

n = len(self.alphabet)<EOL>self.mu = mu<EOL>if pi is not None and len(pi)==n:<EOL><INDENT>Pi = np.array(pi)<EOL><DEDENT>else:<EOL><INDENT>if pi is not None and len(pi)!=n:<EOL><INDENT>self.logger("<STR_LIT>", <NUM_LIT:4>, warn=True)<EOL>self.logger("<STR_LIT>", <NUM_LIT:4>, warn=True)<EOL><DEDENT>Pi = np.ones(shape=(n,))<EOL><DEDENT>self.Pi = Pi/np.sum(Pi)<EOL>if W is None or W.shape!=(n,n):<EOL><INDENT>if (W is not None) and W.shape!=(n,n):<EOL><INDENT>self.logger("<STR_LIT>", <NUM_LIT:4>, warn=True)<EOL>self.logger("<STR_LIT>", <NUM_LIT:4>, warn=True)<EOL><DEDENT>W = np.ones((n,n))<EOL>np.fill_diagonal(W, <NUM_LIT:0.0>)<EOL>np.fill_diagonal(W, - W.sum(axis=<NUM_LIT:0>))<EOL><DEDENT>else:<EOL><INDENT>W=np.array(W)<EOL><DEDENT>self.W = <NUM_LIT:0.5>*(W+W.T)<EOL>self._check_fix_Q(fixed_mu=True)<EOL>self._eig()<EOL>

Overwrite the GTR model given the provided data

Parameters
----------

 mu : float
    Substitution rate

 W : nxn matrix
    Substitution matrix

 pi : n vector
    Equilibrium frequencies


@classmethod<EOL><INDENT>def custom(cls, mu=<NUM_LIT:1.0>, pi=None, W=None, **kwargs):<DEDENT>

gtr = cls(**kwargs)<EOL>gtr.assign_rates(mu=mu, pi=pi, W=W)<EOL>return gtr<EOL>

Create a GTR model by specifying the matrix explicitly

Parameters
----------

 mu : float
    Substitution rate

 W : nxn matrix
    Substitution matrix

 pi : n vector
    Equilibrium frequencies

 **kwargs:
    Key word arguments to be passed

Keyword Args
------------

 alphabet : str
    Specify alphabet when applicable. If the alphabet specification is
    required, but no alphabet is specified, the nucleotide alphabet will be used as
    default.


from .nuc_models import JC69, K80, F81, HKY85, T92, TN93<EOL>from .aa_models  import JTT92<EOL>if model.lower() in ['<STR_LIT>', '<STR_LIT>', '<STR_LIT>', '<STR_LIT>', '<STR_LIT>', '<STR_LIT>']:<EOL><INDENT>return JC69(**kwargs)<EOL><DEDENT>elif model.lower() in ['<STR_LIT>', '<STR_LIT>', '<STR_LIT>']:<EOL><INDENT>return K80(**kwargs)<EOL><DEDENT>elif model.lower() in ['<STR_LIT>', '<STR_LIT>', '<STR_LIT>']:<EOL><INDENT>return F81(**kwargs)<EOL><DEDENT>elif model.lower() in ['<STR_LIT>', '<STR_LIT>', '<STR_LIT>']:<EOL><INDENT>return HKY85(**kwargs)<EOL><DEDENT>elif model.lower() in ['<STR_LIT>', '<STR_LIT>', '<STR_LIT>']:<EOL><INDENT>return T92(**kwargs)<EOL><DEDENT>elif model.lower() in ['<STR_LIT>', '<STR_LIT>', '<STR_LIT>']:<EOL><INDENT>return TN93(**kwargs)<EOL><DEDENT>elif model.lower() in ['<STR_LIT>', '<STR_LIT>']:<EOL><INDENT>return JTT92(**kwargs)<EOL><DEDENT>else:<EOL><INDENT>raise KeyError("<STR_LIT>"<EOL>"<STR_LIT>".format(model))<EOL><DEDENT>

Create standard model of molecular evolution.

Parameters
----------

 model : str
    Model to create. See list of available models below
 **kwargs:
    Key word arguments to be passed to the model

**Available models**

- JC69:

  Jukes-Cantor 1969 model. This model assumes equal frequencies
  of the nucleotides and equal transition rates between nucleotide states.
  For more info, see: Jukes and Cantor (1969).
  Evolution of Protein Molecules. New York: Academic Press. pp. 21-132.
  To create this model, use:

  :code:`mygtr = GTR.standard(model='jc69', mu=<my_mu>, alphabet=<my_alph>)`

  :code:`my_mu` - substitution rate (float)

  :code:`my_alph` - alphabet (str: :code:`'nuc'` or  :code:`'nuc_nogap'`)

- K80:

  Kimura 1980 model. Assumes equal concentrations across nucleotides, but
  allows different rates between transitions and transversions. The ratio
  of the transversion/transition rates is given by kappa parameter.
  For more info, see
  Kimura (1980),  J. Mol. Evol. 16 (2): 111-120. doi:10.1007/BF01731581.
  Current implementation of the model does not account for the gaps.

  :code:`mygtr = GTR.standard(model='k80', mu=<my_mu>, kappa=<my_kappa>)`

  :code:`mu` - overall substitution rate (float)

  :code:`kappa` - ratio of transversion/transition rates (float)

- F81:

  Felsenstein 1981 model. Assumes non-equal concentrations across nucleotides,
  but the transition rate between all states is assumed to be equal. See
  Felsenstein (1981), J. Mol. Evol. 17  (6): 368-376. doi:10.1007/BF01734359
  for details.

  :code:`mygtr = GTR.standard(model='F81', mu=<mu>, pi=<pi>, alphabet=<alph>)`

  :code:`mu` -  substitution rate  (float)

  :code:`pi`  - : nucleotide concentrations (numpy.array)

  :code:`alphabet' -  alphabet to use. (:code:`'nuc'` or  :code:`'nuc_nogap'`)

- HKY85:

  Hasegawa, Kishino and Yano 1985 model. Allows different concentrations of the
  nucleotides (as in F81) + distinguishes between transition/transversion substitutions
  (similar to K80). Link:
  Hasegawa, Kishino, Yano (1985), J. Mol. Evol. 22 (2): 160-174. doi:10.1007/BF02101694

  Current implementation of the model does not account for the gaps

  :code:`mygtr = GTR.standard(model='HKY85', mu=<mu>, pi=<pi>, kappa=<kappa>)`

  :code:`mu` -  substitution rate  (float)

  :code:`pi`  - : nucleotide concentrations (numpy.array)

  :code:`kappa` - ratio of transversion/transition rates (float)

- T92:

  Tamura 1992 model. Extending Kimura  (1980) model for the case where a
  G+C-content bias exists. Link:
  Tamura K (1992),  Mol.  Biol. Evol. 9 (4): 678-687.  DOI: 10.1093/oxfordjournals.molbev.a040752

  Current implementation of the model does not account for the gaps

  :code:`mygtr = GTR.standard(model='T92', mu=<mu>, pi_GC=<pi_gc>, kappa=<kappa>)`

  :code:`mu` -  substitution rate  (float)

  :code:`pi_GC`  - : relative GC content

  :code:`kappa` - ratio of transversion/transition rates (float)

- TN93:

  Tamura and Nei 1993. The model distinguishes between the two different types of
  transition: (A <-> G) is allowed to have a different rate to (C<->T).
  Transversions have the same rate. The frequencies of the nucleotides are allowed
  to be different. Link: Tamura, Nei (1993), MolBiol Evol. 10 (3): 512-526.
  DOI:10.1093/oxfordjournals.molbev.a040023

  :code:`mygtr = GTR.standard(model='TN93', mu=<mu>, kappa1=<k1>, kappa2=<k2>)`

  :code:`mu` -  substitution rate  (float)

  :code:`kappa1`  - relative A<-->C, A<-->T, T<-->G and G<-->C rates (float)

  :code:`kappa` - relative C<-->T rate (float)

  .. Note::
        Rate of A<-->G substitution is set to one. All other rates
        (kappa1, kappa2) are specified relative to this rate


@classmethod<EOL><INDENT>def random(cls, mu=<NUM_LIT:1.0>, alphabet='<STR_LIT>'):<DEDENT>

alphabet=alphabets[alphabet]<EOL>gtr = cls(alphabet)<EOL>n = gtr.alphabet.shape[<NUM_LIT:0>]<EOL>pi = <NUM_LIT:1.0>*np.random.randint(<NUM_LIT:0>,<NUM_LIT:100>,size=(n))<EOL>W = <NUM_LIT:1.0>*np.random.randint(<NUM_LIT:0>,<NUM_LIT:100>,size=(n,n)) <EOL>gtr.assign_rates(mu=mu, pi=pi, W=W)<EOL>return gtr<EOL>

Creates a random GTR model

Parameters
----------

 mu : float
    Substitution rate

 alphabet : str
    Alphabet name (should be standard: 'nuc', 'nuc_gap', 'aa', 'aa_gap')


@classmethod<EOL><INDENT>def infer(cls, nij, Ti, root_state, fixed_pi=None, pc=<NUM_LIT>, gap_limit=<NUM_LIT>, **kwargs):<DEDENT>

from scipy import linalg as LA<EOL>gtr = cls(**kwargs)<EOL>gtr.logger("<STR_LIT>",<NUM_LIT:1>)<EOL>dp = <NUM_LIT><EOL>Nit = <NUM_LIT><EOL>pc_mat = pc*np.ones_like(nij)<EOL>np.fill_diagonal(pc_mat, <NUM_LIT:0.0>)<EOL>count = <NUM_LIT:0><EOL>pi_old = np.zeros_like(Ti)<EOL>if fixed_pi is None:<EOL><INDENT>pi = np.ones_like(Ti)<EOL><DEDENT>else:<EOL><INDENT>pi = np.copy(fixed_pi)<EOL><DEDENT>pi/=pi.sum()<EOL>W_ij = np.ones_like(nij)<EOL>mu = nij.sum()/Ti.sum()<EOL>while LA.norm(pi_old-pi) > dp and count < Nit:<EOL><INDENT>gtr.logger('<STR_LIT:U+0020>'.join(map(str, ['<STR_LIT>',count,'<STR_LIT>',LA.norm(pi_old-pi)])), <NUM_LIT:3>)<EOL>count += <NUM_LIT:1><EOL>pi_old = np.copy(pi)<EOL>W_ij = (nij+nij.T+<NUM_LIT:2>*pc_mat)/mu/(np.outer(pi,Ti) + np.outer(Ti,pi)<EOL>+ ttconf.TINY_NUMBER + <NUM_LIT:2>*pc_mat)<EOL>np.fill_diagonal(W_ij, <NUM_LIT:0>)<EOL>scale_factor = np.einsum('<STR_LIT>',pi,W_ij,pi)<EOL>W_ij = W_ij/scale_factor<EOL>if fixed_pi is None:<EOL><INDENT>pi = (np.sum(nij+pc_mat,axis=<NUM_LIT:1>)+root_state)/(ttconf.TINY_NUMBER + mu*np.dot(W_ij,Ti)+root_state.sum()+np.sum(pc_mat, axis=<NUM_LIT:1>))<EOL>pi /= pi.sum()<EOL><DEDENT>mu = nij.sum()/(ttconf.TINY_NUMBER + np.sum(pi * (W_ij.dot(Ti))))<EOL><DEDENT>if count >= Nit:<EOL><INDENT>gtr.logger('<STR_LIT>',<NUM_LIT:3>, warn=True)<EOL>if LA.norm(pi_old-pi) > dp:<EOL><INDENT>gtr.logger('<STR_LIT>',<NUM_LIT:3>,warn=True)<EOL><DEDENT>elif np.abs(<NUM_LIT:1>-np.max(pi.sum(axis=<NUM_LIT:0>))) > dp:<EOL><INDENT>gtr.logger('<STR_LIT>',<NUM_LIT:3>,warn=True)<EOL><DEDENT><DEDENT>if gtr.gap_index is not None:<EOL><INDENT>if pi[gtr.gap_index]<gap_limit:<EOL><INDENT>gtr.logger('<STR_LIT>'%pi[gtr.gap_index]+<EOL>'<STR_LIT>'+<EOL>'<STR_LIT>'%gap_limit,<NUM_LIT:2>,warn=True)<EOL><DEDENT>pi[gtr.gap_index] = gap_limit<EOL>pi /= pi.sum()<EOL><DEDENT>gtr.assign_rates(mu=mu, W=W_ij, pi=pi)<EOL>return gtr<EOL>

Infer a GTR model by specifying the number of transitions and time spent in each
character. The basic equation that is being solved is

:math:`n_{ij} = pi_i W_{ij} T_j`

where :math:`n_{ij}` are the transitions, :math:`pi_i` are the equilibrium
state frequencies, :math:`W_{ij}` is the "substitution attempt matrix",
while :math:`T_i` is the time on the tree spent in character state
:math:`i`. To regularize the process, we add pseudocounts and also need
to account for the fact that the root of the tree is in a particular
state. the modified equation is

:math:`n_{ij} + pc = pi_i W_{ij} (T_j+pc+root\_state)`

Parameters
----------

 nij : nxn matrix
    The number of times a change in character state is observed
    between state j and i

 Ti :n vector
    The time spent in each character state

 root_state : n vector
    The number of characters in state i in the sequence
    of the root node.

 pc : float
    Pseudocounts, this determines the lower cutoff on the rate when
    no substitutions are observed

 **kwargs:
    Key word arguments to be passed

Keyword Args
------------

 alphabet : str
    Specify alphabet when applicable. If the alphabet specification
    is required, but no alphabet is specified, the nucleotide alphabet will be used as default.


<EOL>self.Pi /= self.Pi.sum() <EOL>self.W += self.break_degen + self.break_degen.T<EOL>np.fill_diagonal(self.W, <NUM_LIT:0>)<EOL>Wdiag = -(self.Q).sum(axis=<NUM_LIT:0>)/self.Pi<EOL>np.fill_diagonal(self.W, Wdiag)<EOL>scale_factor = -np.sum(np.diagonal(self.Q)*self.Pi)<EOL>self.W /= scale_factor<EOL>if not fixed_mu:<EOL><INDENT>self.mu *= scale_factor<EOL><DEDENT>if (self.Q.sum(axis=<NUM_LIT:0>) < <NUM_LIT>).sum() <  self.alphabet.shape[<NUM_LIT:0>]: <EOL><INDENT>print ("<STR_LIT>", self.Q.sum(axis=<NUM_LIT:0>))<EOL>import ipdb; ipdb.set_trace()<EOL>raise ArithmeticError("<STR_LIT>")<EOL><DEDENT>

Check the main diagonal of Q and fix it in case it does not corresond
the definition of the rate matrix. Should be run every time when creating
custom GTR model.


<EOL>eigvals, eigvecs = np.linalg.eig(self.Q)<EOL>self.v = np.real(eigvecs)<EOL>self.v_inv = np.linalg.inv(self.v)<EOL>self.eigenvals = np.real(eigvals)<EOL>

Perform eigendecompositon of the rate matrix and stores the left- and right-
matrices to convert the sequence profiles to the GTR matrix eigenspace
and hence to speed-up the computations.


<EOL>tmpp = np.sqrt(self.Pi)<EOL>symQ = self.W*np.outer(tmpp, tmpp)<EOL>eigvals, eigvecs = np.linalg.eigh(symQ)<EOL>tmp_v = eigvecs.T*tmpp<EOL>one_norm = np.sum(np.abs(tmp_v), axis=<NUM_LIT:1>)<EOL>self.v = tmp_v.T/one_norm<EOL>self.v_inv = (eigvecs*one_norm).T/tmpp<EOL>self.eigenvals = eigvals<EOL>


def compress_sequence_pair(self, seq_p, seq_ch, pattern_multiplicity=None,<EOL>ignore_gaps=False):

if pattern_multiplicity is None:<EOL><INDENT>pattern_multiplicity = np.ones_like(seq_p, dtype=float)<EOL><DEDENT>from collections import Counter<EOL>if seq_ch.shape != seq_p.shape:<EOL><INDENT>raise ValueError("<STR_LIT>")<EOL><DEDENT>if len(self.alphabet)<<NUM_LIT:10>: <EOL><INDENT>pair_count = []<EOL>bool_seqs_p = []<EOL>bool_seqs_ch = []<EOL>for seq, bs in [(seq_p,bool_seqs_p), (seq_ch, bool_seqs_ch)]:<EOL><INDENT>for ni,nuc in enumerate(self.alphabet):<EOL><INDENT>bs.append(seq==nuc)<EOL><DEDENT><DEDENT>for n1,nuc1 in enumerate(self.alphabet):<EOL><INDENT>if (self.gap_index is None) or (not ignore_gaps) or (n1!=self.gap_index):<EOL><INDENT>for n2,nuc2 in enumerate(self.alphabet):<EOL><INDENT>if (self.gap_index is None) or (not ignore_gaps) or (n2!=self.gap_index):<EOL><INDENT>count = ((bool_seqs_p[n1]&bool_seqs_ch[n2])*pattern_multiplicity).sum()<EOL>if count: pair_count.append(((n1,n2), count))<EOL><DEDENT><DEDENT><DEDENT><DEDENT><DEDENT>else: <EOL><INDENT>num_seqs = []<EOL>for seq in [seq_p, seq_ch]: <EOL><INDENT>tmp = np.ones_like(seq, dtype=int)<EOL>for ni,nuc in enumerate(self.alphabet):<EOL><INDENT>tmp[seq==nuc] = ni  <EOL><DEDENT>num_seqs.append(tmp)<EOL><DEDENT>pair_count = defaultdict(int)<EOL>if ignore_gaps:  <EOL><INDENT>for i in range(len(seq_p)):<EOL><INDENT>if self.gap_index!=num_seqs[<NUM_LIT:0>][i] and self.gap_index!=num_seqs[<NUM_LIT:1>][i]:<EOL><INDENT>pair_count[(num_seqs[<NUM_LIT:0>][i],num_seqs[<NUM_LIT:1>][i])]+=pattern_multiplicity[i]<EOL><DEDENT><DEDENT><DEDENT>else: <EOL><INDENT>for i in range(len(seq_p)):<EOL><INDENT>pair_count[(num_seqs[<NUM_LIT:0>][i],num_seqs[<NUM_LIT:1>][i])]+=pattern_multiplicity[i]<EOL><DEDENT><DEDENT>pair_count = pair_count.items()<EOL><DEDENT>return (np.array([x[<NUM_LIT:0>] for x in pair_count], dtype=int),    <EOL>np.array([x[<NUM_LIT:1>] for x in pair_count], dtype=int))<EOL>

Make a compressed representation of a pair of sequences, only counting
the number of times a particular pair of states (e.g. (A,T)) is observed
in the aligned sequences of parent and child.

Parameters
----------

 seq_p: numpy array
    Parent sequence as numpy array of chars

 seq_ch: numpy array
    Child sequence as numpy array of chars

 pattern_multiplicity : numpy array
    If sequences are reduced by combining identical alignment patterns,
    these multplicities need to be accounted for when counting the number
    of mutations across a branch. If None, all pattern are assumed to
    occur exactly once.

 ignore_gap: bool
    Whether or not to include gapped positions of the alignment
    in the multiplicity count

Returns
-------
  seq_pair : list
    :code:`[(0,1), (2,2), (3,4)]` list of parent_child state pairs
    as indices in the alphabet

  multiplicity : numpy array
    Number of times a particular pair is observed


def prob_t_compressed(self, seq_pair, multiplicity, t, return_log=False):

if t<<NUM_LIT:0>:<EOL><INDENT>logP = -ttconf.BIG_NUMBER<EOL><DEDENT>else:<EOL><INDENT>tmp_eQT = self.expQt(t)<EOL>bad_indices=(tmp_eQT==<NUM_LIT:0>)<EOL>logQt = np.log(tmp_eQT + ttconf.TINY_NUMBER*(bad_indices))<EOL>logQt[np.isnan(logQt) | np.isinf(logQt) | bad_indices] = -ttconf.BIG_NUMBER<EOL>logP = np.sum(logQt[seq_pair[:,<NUM_LIT:1>], seq_pair[:,<NUM_LIT:0>]]*multiplicity)<EOL><DEDENT>return logP if return_log else np.exp(logP)<EOL>

Calculate the probability of observing a sequence pair at a distance t,
for compressed sequences

Parameters
----------

  seq_pair : numpy array
    :code:`np.array([(0,1), (2,2), ()..])` as indicies of
    pairs of aligned positions. (e.g. 'A'==0, 'C'==1 etc).
    This only lists all occuring parent-child state pairs, order is irrelevant

  multiplicity : numpy array
    The number of times a parent-child state pair is observed.
    This allows compression of the sequence representation

  t : float
    Length of the branch separating parent and child

  return_log : bool
    Whether or not to exponentiate the result


def prob_t(self, seq_p, seq_ch, t, pattern_multiplicity = None,<EOL>return_log=False, ignore_gaps=True):

seq_pair, multiplicity = self.compress_sequence_pair(seq_p, seq_ch,<EOL>pattern_multiplicity=pattern_multiplicity, ignore_gaps=ignore_gaps)<EOL>return self.prob_t_compressed(seq_pair, multiplicity, t, return_log=return_log)<EOL>

Compute the probability to observe seq_ch (child sequence) after time t starting from seq_p
(parent sequence).

Parameters
----------

 seq_p : character array
    Parent sequence

 seq_c : character array
    Child sequence

 t : double
    Time (branch len) separating the profiles.

 pattern_multiplicity : numpy array
    If sequences are reduced by combining identical alignment patterns,
    these multplicities need to be accounted for when counting the number
    of mutations across a branch. If None, all pattern are assumed to
    occur exactly once.

 return_log : bool
    It True, return log-probability.

Returns
-------
 prob : np.array
    Resulting probability


def optimal_t(self, seq_p, seq_ch, pattern_multiplicity=None, ignore_gaps=False):

seq_pair, multiplicity = self.compress_sequence_pair(seq_p, seq_ch,<EOL>pattern_multiplicity = pattern_multiplicity,<EOL>ignore_gaps=ignore_gaps)<EOL>return self.optimal_t_compressed(seq_pair, multiplicity)<EOL>

Find the optimal distance between the two sequences

Parameters
----------

 seq_p : character array
    Parent sequence

 seq_c : character array
    Child sequence

 pattern_multiplicity : numpy array
    If sequences are reduced by combining identical alignment patterns,
    these multplicities need to be accounted for when counting the number
    of mutations across a branch. If None, all pattern are assumed to
    occur exactly once.

 ignore_gaps : bool
    If True, ignore gaps in distance calculations


def optimal_t_compressed(self, seq_pair, multiplicity, profiles=False, tol=<NUM_LIT>):

def _neg_prob(t, seq_pair, multiplicity):<EOL><INDENT>"""<STR_LIT>"""<EOL>if profiles:<EOL><INDENT>res = -<NUM_LIT:1.0>*self.prob_t_profiles(seq_pair, multiplicity,t**<NUM_LIT:2>, return_log=True)<EOL>return res<EOL><DEDENT>else:<EOL><INDENT>return -<NUM_LIT:1.0>*self.prob_t_compressed(seq_pair, multiplicity,t**<NUM_LIT:2>, return_log=True)<EOL><DEDENT><DEDENT>try:<EOL><INDENT>from scipy.optimize import minimize_scalar<EOL>opt = minimize_scalar(_neg_prob,<EOL>bounds=[-np.sqrt(ttconf.MAX_BRANCH_LENGTH),np.sqrt(ttconf.MAX_BRANCH_LENGTH)],<EOL>args=(seq_pair, multiplicity), tol=tol)<EOL>new_len = opt["<STR_LIT:x>"]**<NUM_LIT:2><EOL>if '<STR_LIT:success>' not in opt:<EOL><INDENT>opt['<STR_LIT:success>'] = True<EOL>self.logger("<STR_LIT>"+str(opt),<NUM_LIT:4>, warn=True)<EOL><DEDENT><DEDENT>except:<EOL><INDENT>import scipy<EOL>print('<STR_LIT>', scipy.__version__)<EOL>from scipy.optimize import fminbound<EOL>new_len = fminbound(_neg_prob,<EOL>-np.sqrt(ttconf.MAX_BRANCH_LENGTH),np.sqrt(ttconf.MAX_BRANCH_LENGTH),<EOL>args=(seq_pair, multiplicity))<EOL>new_len = new_len**<NUM_LIT:2><EOL>opt={'<STR_LIT:success>':True}<EOL><DEDENT>if new_len > <NUM_LIT> * ttconf.MAX_BRANCH_LENGTH:<EOL><INDENT>self.logger("<STR_LIT>", <NUM_LIT:4>, warn=True)<EOL><DEDENT>if opt["<STR_LIT:success>"] != True:<EOL><INDENT>new_len =  np.sum(multiplicity[seq_pair[:,<NUM_LIT:1>]!=seq_pair[:,<NUM_LIT:0>]])/np.sum(multiplicity)<EOL><DEDENT>return new_len<EOL>

Find the optimal distance between the two sequences, for compressed sequences

Parameters
----------

 seq_pair : compressed_sequence_pair
    Compressed representation of sequences along a branch, either
    as tuple of state pairs or as tuple of profiles.

 multiplicity : array
    Number of times each state pair in seq_pair appears (if profile==False)

    Number of times an alignment pattern is observed (if profiles==True)

 profiles : bool, default False
    The standard branch length optimization assumes fixed sequences at
    either end of the branch. With profiles==True, optimization is performed
    while summing over all possible states of the nodes at either end of the
    branch. Note that the meaning/format of seq_pair and multiplicity
    depend on the value of profiles.


def prob_t_profiles(self, profile_pair, multiplicity, t,<EOL>return_log=False, ignore_gaps=True):

if t<<NUM_LIT:0>:<EOL><INDENT>logP = -ttconf.BIG_NUMBER<EOL><DEDENT>else:<EOL><INDENT>Qt = self.expQt(t)<EOL>if len(Qt.shape)==<NUM_LIT:3>:<EOL><INDENT>res = np.einsum('<STR_LIT>', profile_pair[<NUM_LIT:1>], Qt, profile_pair[<NUM_LIT:0>])<EOL><DEDENT>else:<EOL><INDENT>res = np.einsum('<STR_LIT>', profile_pair[<NUM_LIT:1>], Qt, profile_pair[<NUM_LIT:0>])<EOL><DEDENT>if ignore_gaps and (self.gap_index is not None): <EOL><INDENT>non_gap_frac = (<NUM_LIT:1>-profile_pair[<NUM_LIT:0>][:,self.gap_index])*(<NUM_LIT:1>-profile_pair[<NUM_LIT:1>][:,self.gap_index])<EOL>logP = np.sum(multiplicity*np.log(res)*non_gap_frac)<EOL><DEDENT>else:<EOL><INDENT>logP = np.sum(multiplicity*np.log(res))<EOL><DEDENT><DEDENT>return logP if return_log else np.exp(logP)<EOL>

Calculate the probability of observing a node pair at a distance t

Parameters
----------

  profile_pair: numpy arrays
    Probability distributions of the nucleotides at either
    end of the branch. pp[0] = parent, pp[1] = child

  multiplicity : numpy array
    The number of times an alignment pattern is observed

  t : float
    Length of the branch separating parent and child

  ignore_gaps: bool
    If True, ignore mutations to and from gaps in distance calculations

  return_log : bool
    Whether or not to exponentiate the result


def propagate_profile(self, profile, t, return_log=False):

Qt = self.expQt(t)<EOL>res = profile.dot(Qt)<EOL>return np.log(res) if return_log else res<EOL>

Compute the probability of the sequence state of the parent
at time (t+t0, backwards), given the sequence state of the
child (profile) at time t0.

Parameters
----------

 profile : numpy.array
    Sequence profile. Shape = (L, a),
    where L - sequence length, a - alphabet size.

 t : double
    Time to propagate

 return_log: bool
    If True, return log-probability

Returns
-------

 res : np.array
    Profile of the sequence after time t in the past.
    Shape = (L, a), where L - sequence length, a - alphabet size.


def evolve(self, profile, t, return_log=False):

Qt = self.expQt(t).T<EOL>res = profile.dot(Qt)<EOL>return np.log(res) if return_log else res<EOL>

Compute the probability of the sequence state of the child
at time t later, given the parent profile.

Parameters
----------

 profile : numpy.array
    Sequence profile. Shape = (L, a),
    where L - sequence length, a - alphabet size.

 t : double
    Time to propagate

 return_log: bool
    If True, return log-probability

Returns
-------

 res : np.array
    Profile of the sequence after time t in the future.
    Shape = (L, a), where L - sequence length, a - alphabet size.


return np.exp(self.mu * t * self.eigenvals)<EOL>

Parameters
----------

 t : float
    time to propagate

Returns
--------

 exp_lt : numpy.array
    Array of values exp(lambda(i) * t),
    where (i) - alphabet index (the eigenvalue number).


eLambdaT = np.diag(self._exp_lt(t)) <EOL>Qs = self.v.dot(eLambdaT.dot(self.v_inv))   <EOL>return np.maximum(<NUM_LIT:0>,Qs)<EOL>

Parameters
----------

 t : float
    Time to propagate

Returns
--------

 expQt : numpy.array
    Matrix exponential of exo(Qt)


lambda_eLambdaT = np.diag(<NUM_LIT>*self._exp_lt(s**<NUM_LIT:2>)*self.eigenvals*s) <EOL>Qsds = self.v.dot(lambda_eLambdaT.dot(self.v_inv))<EOL>return Qsds<EOL>

Returns
-------
Qtds :  Returns 2 V_{ij} \lambda_j s e^{\lambda_j s**2 } V^{-1}_{jk}
        This is the derivative of the branch probability with respect to s=\sqrt(t)


t=s**<NUM_LIT:2><EOL>elt = self._exp_lt(t)<EOL>lambda_eLambdaT = np.diag(elt*(<NUM_LIT>*t*self.eigenvals**<NUM_LIT:2> + <NUM_LIT>*self.eigenvals))<EOL>Qsdsds = self.v.dot(lambda_eLambdaT.dot(self.v_inv))<EOL>return Qsdsds<EOL>

Returns
-------
Qtdtdt :  Returns V_{ij} \lambda_j^2 e^{\lambda_j s**2} V^{-1}_{jk}
        This is the second derivative of the branch probability wrt time


if pattern_multiplicity is None:<EOL><INDENT>pattern_multiplicity = np.ones_like(seq, dtype=float)<EOL><DEDENT>return np.sum([np.sum((seq==state)*pattern_multiplicity*np.log(self.Pi[si]))<EOL>for si,state in enumerate(self.alphabet)])<EOL>

Returns the log-likelihood of sampling a sequence from equilibrium frequency.
Expects a sequence as numpy array

Parameters
----------

 seq : numpy array
    Compressed sequence as an array of chars

 pattern_multiplicity : numpy_array
    The number of times each position in sequence is observed in the
    initial alignment. If None, sequence is assumed to be not compressed


def plot_vs_years(tt, step = None, ax=None, confidence=None, ticks=True, **kwargs):

import matplotlib.pyplot as plt<EOL>tt.branch_length_to_years()<EOL>nleafs = tt.tree.count_terminals()<EOL>if ax is None:<EOL><INDENT>fig = plt.figure(figsize=(<NUM_LIT:12>,<NUM_LIT:10>))<EOL>ax = plt.subplot(<NUM_LIT>)<EOL><DEDENT>else:<EOL><INDENT>fig = None<EOL><DEDENT>if "<STR_LIT>" not in kwargs:<EOL><INDENT>kwargs["<STR_LIT>"] = lambda x:x.name if (x.is_terminal() and nleafs<<NUM_LIT:30>) else "<STR_LIT>"<EOL><DEDENT>Phylo.draw(tt.tree, axes=ax, **kwargs)<EOL>offset = tt.tree.root.numdate - tt.tree.root.branch_length<EOL>date_range = np.max([n.numdate for n in tt.tree.get_terminals()])-offset<EOL>if step is None or (step><NUM_LIT:0> and date_range/step><NUM_LIT:100>):<EOL><INDENT>step = <NUM_LIT:10>**np.floor(np.log10(date_range))<EOL>if date_range/step<<NUM_LIT:2>:<EOL><INDENT>step/=<NUM_LIT:5><EOL><DEDENT>elif date_range/step<<NUM_LIT:5>:<EOL><INDENT>step/=<NUM_LIT:2><EOL><DEDENT>step = max(<NUM_LIT:1.0>/<NUM_LIT:12>,step)<EOL><DEDENT>if step:<EOL><INDENT>dtick = step<EOL>min_tick = step*(offset//step)<EOL>extra = dtick if dtick<date_range else dtick<EOL>tick_vals = np.arange(min_tick, min_tick+date_range+extra, dtick)<EOL>xticks = tick_vals - offset<EOL><DEDENT>else:<EOL><INDENT>xticks = ax.get_xticks()<EOL>dtick = xticks[<NUM_LIT:1>]-xticks[<NUM_LIT:0>]<EOL>shift = offset - dtick*(offset//dtick)<EOL>xticks -= shift<EOL>tick_vals = [x+offset-shift for x in xticks]<EOL><DEDENT>ax.set_xticks(xticks)<EOL>ax.set_xticklabels(map(str, tick_vals))<EOL>ax.set_xlabel('<STR_LIT>')<EOL>ax.set_ylabel('<STR_LIT>')<EOL>ax.set_xlim((<NUM_LIT:0>,date_range))<EOL>if step:<EOL><INDENT>ylim = ax.get_ylim()<EOL>xlim = ax.get_xlim()<EOL>from matplotlib.patches import Rectangle<EOL>for yi,year in enumerate(np.arange(np.floor(tick_vals[<NUM_LIT:0>]), tick_vals[-<NUM_LIT:1>]+<NUM_LIT>, step)):<EOL><INDENT>pos = year - offset<EOL>r = Rectangle((pos, ylim[<NUM_LIT:1>]-<NUM_LIT:5>),<EOL>step, ylim[<NUM_LIT:0>]-ylim[<NUM_LIT:1>]+<NUM_LIT:10>,<EOL>facecolor=[<NUM_LIT>+<NUM_LIT:0.1>*(<NUM_LIT:1>+yi%<NUM_LIT:2>)] * <NUM_LIT:3>,<EOL>edgecolor=[<NUM_LIT:1>,<NUM_LIT:1>,<NUM_LIT:1>])<EOL>ax.add_patch(r)<EOL>if year in tick_vals and pos>=xlim[<NUM_LIT:0>] and pos<=xlim[<NUM_LIT:1>] and ticks:<EOL><INDENT>label_str = str(step*(year//step)) if step<<NUM_LIT:1> else  str(int(year))<EOL>ax.text(pos,ylim[<NUM_LIT:0>]-<NUM_LIT>*(ylim[<NUM_LIT:1>]-ylim[<NUM_LIT:0>]), label_str,<EOL>horizontalalignment='<STR_LIT>')<EOL><DEDENT><DEDENT>ax.set_axis_off()<EOL><DEDENT>if confidence:<EOL><INDENT>tree_layout(tt.tree)<EOL>if not hasattr(tt.tree.root, "<STR_LIT>"):<EOL><INDENT>print("<STR_LIT>")<EOL>return ttconf.ERROR<EOL><DEDENT>elif type(confidence) is float:<EOL><INDENT>cfunc = tt.get_max_posterior_region<EOL><DEDENT>elif len(confidence)==<NUM_LIT:2>:<EOL><INDENT>cfunc = tt.get_confidence_interval<EOL><DEDENT>else:<EOL><INDENT>print("<STR_LIT>")<EOL>return ttconf.ERROR<EOL><DEDENT>for n in tt.tree.find_clades():<EOL><INDENT>pos = cfunc(n, confidence)<EOL>ax.plot(pos-offset, np.ones(len(pos))*n.ypos, lw=<NUM_LIT:3>, c=(<NUM_LIT:0.5>,<NUM_LIT:0.5>,<NUM_LIT:0.5>))<EOL><DEDENT><DEDENT>return fig, ax<EOL>

Converts branch length to years and plots the time tree on a time axis.

Parameters
----------
 tt : TreeTime object
    A TreeTime instance after a time tree is inferred

 step : int
    Width of shaded boxes indicating blocks of years. Will be inferred if not specified.
    To switch off drawing of boxes, set to 0

 ax : matplotlib axes
    Axes to be used to plot, will create new axis if None

 confidence : tuple, float
    Draw confidence intervals. This assumes that marginal time tree inference was run.
    Confidence intervals are either specified as an interval of the posterior distribution
    like (0.05, 0.95) or as the weight of the maximal posterior region , e.g. 0.9

 **kwargs : dict
    Key word arguments that are passed down to Phylo.draw


super(TreeTime, self).__init__(*args, **kwargs)<EOL>

TreeTime constructor

Parameters
-----------
 *args
    Arguments to construct ClockTree

 **kwargs
    Keyword arguments to construct the GTR model


def run(self, root=None, infer_gtr=True, relaxed_clock=None, n_iqd = None,<EOL>resolve_polytomies=True, max_iter=<NUM_LIT:0>, Tc=None, fixed_clock_rate=None,<EOL>time_marginal=False, sequence_marginal=False, branch_length_mode='<STR_LIT>',<EOL>vary_rate=False, use_covariation=False, **kwargs):

<EOL>self.use_covariation = use_covariation<EOL>if (self.tree is None) or (self.aln is None and self.seq_len is None):<EOL><INDENT>self.logger("<STR_LIT>", <NUM_LIT:0>)<EOL>return ttconf.ERROR<EOL><DEDENT>if (self.aln is None):<EOL><INDENT>branch_length_mode='<STR_LIT:input>'<EOL><DEDENT>self._set_branch_length_mode(branch_length_mode)<EOL>seq_kwargs = {"<STR_LIT>":sequence_marginal or (self.branch_length_mode=='<STR_LIT>'),<EOL>"<STR_LIT>":"<STR_LIT:root>"}<EOL>tt_kwargs = {'<STR_LIT>':fixed_clock_rate, '<STR_LIT>':False}<EOL>tt_kwargs.update(kwargs)<EOL>seq_LH = <NUM_LIT:0><EOL>if "<STR_LIT>" in kwargs:<EOL><INDENT>seq_kwargs["<STR_LIT>"] = kwargs["<STR_LIT>"]<EOL><DEDENT>if "<STR_LIT>" in kwargs:<EOL><INDENT>time_marginal=kwargs["<STR_LIT>"]<EOL><DEDENT>if self.branch_length_mode=='<STR_LIT:input>':<EOL><INDENT>if self.aln:<EOL><INDENT>self.infer_ancestral_sequences(infer_gtr=infer_gtr, **seq_kwargs)<EOL>self.prune_short_branches()<EOL><DEDENT><DEDENT>else:<EOL><INDENT>self.optimize_sequences_and_branch_length(infer_gtr=infer_gtr,<EOL>max_iter=<NUM_LIT:1>, prune_short=True, **seq_kwargs)<EOL><DEDENT>avg_root_to_tip = np.mean([x.dist2root for x in self.tree.get_terminals()])<EOL>if n_iqd or root=='<STR_LIT>':<EOL><INDENT>if "<STR_LIT>" in kwargs and kwargs["<STR_LIT>"]:<EOL><INDENT>plot_rtt=True<EOL><DEDENT>else:<EOL><INDENT>plot_rtt=False<EOL><DEDENT>reroot_mechanism = '<STR_LIT>' if root=='<STR_LIT>' else root<EOL>if self.clock_filter(reroot=reroot_mechanism, n_iqd=n_iqd, plot=plot_rtt)==ttconf.ERROR:<EOL><INDENT>return ttconf.ERROR<EOL><DEDENT><DEDENT>elif root is not None:<EOL><INDENT>if self.reroot(root=root)==ttconf.ERROR:<EOL><INDENT>return ttconf.ERROR<EOL><DEDENT><DEDENT>if self.branch_length_mode=='<STR_LIT:input>':<EOL><INDENT>if self.aln:<EOL><INDENT>self.infer_ancestral_sequences(**seq_kwargs)<EOL><DEDENT><DEDENT>else:<EOL><INDENT>self.optimize_sequences_and_branch_length(max_iter=<NUM_LIT:1>, prune_short=False,<EOL>**seq_kwargs)<EOL><DEDENT>self.logger("<STR_LIT>",<NUM_LIT:0>)<EOL>self.make_time_tree(**tt_kwargs)<EOL>if self.aln:<EOL><INDENT>seq_LH = self.tree.sequence_marginal_LH if seq_kwargs['<STR_LIT>'] else self.tree.sequence_joint_LH<EOL><DEDENT>self.LH =[[seq_LH, self.tree.positional_joint_LH, <NUM_LIT:0>]]<EOL>if root is not None and max_iter:<EOL><INDENT>if self.reroot(root='<STR_LIT>' if root=='<STR_LIT>' else root)==ttconf.ERROR:<EOL><INDENT>return ttconf.ERROR<EOL><DEDENT><DEDENT>niter = <NUM_LIT:0><EOL>ndiff = <NUM_LIT:0><EOL>need_new_time_tree=False<EOL>while niter < max_iter:<EOL><INDENT>self.logger("<STR_LIT>"%(niter+<NUM_LIT:1>,max_iter),<NUM_LIT:0>)<EOL>if Tc:<EOL><INDENT>if Tc=='<STR_LIT>' and niter<max_iter-<NUM_LIT:1>:<EOL><INDENT>tmpTc='<STR_LIT>'<EOL><DEDENT>else:<EOL><INDENT>tmpTc=Tc<EOL><DEDENT>self.add_coalescent_model(tmpTc, **kwargs)<EOL>need_new_time_tree = True<EOL><DEDENT>if relaxed_clock:<EOL><INDENT>print("<STR_LIT>", relaxed_clock)<EOL>self.relaxed_clock(**relaxed_clock)<EOL>need_new_time_tree = True<EOL><DEDENT>n_resolved=<NUM_LIT:0><EOL>if resolve_polytomies:<EOL><INDENT>n_resolved = self.resolve_polytomies()<EOL>if n_resolved:<EOL><INDENT>self.prepare_tree()<EOL>if self.branch_length_mode!='<STR_LIT:input>': <EOL><INDENT>self.optimize_sequences_and_branch_length(prune_short=False,<EOL>max_iter=<NUM_LIT:0>, **seq_kwargs)<EOL><DEDENT>need_new_time_tree = True<EOL><DEDENT><DEDENT>if need_new_time_tree:<EOL><INDENT>self.make_time_tree(**tt_kwargs)<EOL>if self.aln:<EOL><INDENT>ndiff = self.infer_ancestral_sequences('<STR_LIT>',**seq_kwargs)<EOL><DEDENT><DEDENT>else: <EOL><INDENT>if self.aln:<EOL><INDENT>ndiff = self.infer_ancestral_sequences('<STR_LIT>',**seq_kwargs)<EOL><DEDENT>self.make_time_tree(**tt_kwargs)<EOL><DEDENT>self.tree.coalescent_joint_LH = self.merger_model.total_LH() if Tc else <NUM_LIT:0.0><EOL>if self.aln:<EOL><INDENT>seq_LH = self.tree.sequence_marginal_LH if seq_kwargs['<STR_LIT>'] else self.tree.sequence_joint_LH<EOL><DEDENT>self.LH.append([seq_LH, self.tree.positional_joint_LH, self.tree.coalescent_joint_LH])<EOL>niter+=<NUM_LIT:1><EOL>if ndiff==<NUM_LIT:0> and n_resolved==<NUM_LIT:0> and Tc!='<STR_LIT>':<EOL><INDENT>self.logger("<STR_LIT>",<NUM_LIT:0>)<EOL>break<EOL><DEDENT><DEDENT>if vary_rate:<EOL><INDENT>if type(vary_rate)==float:<EOL><INDENT>res = self.calc_rate_susceptibility(rate_std=vary_rate, params=tt_kwargs)<EOL><DEDENT>elif self.clock_model['<STR_LIT>']:<EOL><INDENT>res = self.calc_rate_susceptibility(params=tt_kwargs)<EOL><DEDENT>else:<EOL><INDENT>res = ttconf.ERROR<EOL><DEDENT>if res==ttconf.ERROR:<EOL><INDENT>self.logger("<STR_LIT>", <NUM_LIT:1>, warn=True)<EOL><DEDENT><DEDENT>if time_marginal:<EOL><INDENT>self.logger("<STR_LIT>", <NUM_LIT:0>)<EOL>tt_kwargs['<STR_LIT>']=time_marginal<EOL>self.make_time_tree(**tt_kwargs)<EOL><DEDENT>bad_branches =[n for n in self.tree.get_terminals()<EOL>if n.bad_branch and n.raw_date_constraint]<EOL>if bad_branches:<EOL><INDENT>self.logger("<STR_LIT>"<EOL>"<STR_LIT>",<NUM_LIT:0>,warn=True)<EOL>for n in bad_branches:<EOL><INDENT>self.logger("<STR_LIT>"%(n.name, str(n.raw_date_constraint), n.numdate),<NUM_LIT:0>,warn=True)<EOL><DEDENT><DEDENT>return ttconf.SUCCESS<EOL>

Run TreeTime reconstruction. Based on the input parameters, it divides
the analysis into semi-independent jobs and conquers them one-by-one,
gradually optimizing the tree given the temporal constarints and leaf
node sequences.

Parameters
----------
root : str
   Try to find better root position on a given tree. If string is passed,
   the root will be searched according to the specified method. If none,
   use tree as-is.

   See :py:meth:`treetime.TreeTime.reroot` for available rooting methods.

infer_gtr : bool
   If True, infer GTR model

relaxed_clock : dic
   If not None, use autocorrelated molecular clock model. Specify the
   clock parameters as :code:`{slack:<slack>, coupling:<coupling>}` dictionary.

n_iqd : int
   If not None, filter tree nodes which do not obey the molecular clock
   for the particular tree. The nodes, which deviate more than
   :code:`n_iqd` interquantile intervals from the molecular clock
   regression will be marked as 'BAD' and not used in the TreeTime
   analysis

resolve_polytomies : bool
   If True, attempt to resolve multiple mergers

max_iter : int
   Maximum number of iterations to optimize the tree

Tc : float, str
   If not None, use coalescent model to correct the branch lengths by
   introducing merger costs.

   If Tc is float, it is interpreted as the coalescence time scale

   If Tc is str, it should be one of (:code:`opt`, :code:`const`, :code:`skyline`)

fixed_clock_rate : float
   Fixed clock rate to be used. If None, infer clock rate from the molecular clock.

time_marginal : bool
   If True, perform a final round of marginal reconstruction of the node's positions.

sequence_marginal : bool, optional
    use marginal reconstruction for ancestral sequences

branch_length_mode : str
   Should be one of: :code:`joint`, :code:`marginal`, :code:`input`.

   If 'input', rely on the branch lengths in the input tree and skip directly
   to the maximum-likelihood ancestral sequence reconstruction.
   Otherwise, perform preliminary sequence reconstruction using parsimony
   algorithm and do branch length optimization

vary_rate : bool or float, optional
    redo the time tree estimation for rates +/- one standard deviation.
    if a float is passed, it is interpreted as standard deviation,
    otherwise this standard deviation is estimated from the root-to-tip regression

use_covariation : bool, optional
    default False, if False, rate estimates will be performed using simple
    regression ignoring phylogenetic covaration between nodes.

**kwargs
   Keyword arguments needed by the downstream functions

Returns
-------
TreeTime error/succces code : str
    return value depending on success or error


if branch_length_mode in ['<STR_LIT>', '<STR_LIT>', '<STR_LIT:input>']:<EOL><INDENT>self.branch_length_mode = branch_length_mode<EOL><DEDENT>elif self.aln:<EOL><INDENT>bl_dis = [n.branch_length for n in self.tree.find_clades() if n.up]<EOL>max_bl = np.max(bl_dis)<EOL>if max_bl><NUM_LIT:0.1>:<EOL><INDENT>bl_mode = '<STR_LIT:input>'<EOL><DEDENT>else:<EOL><INDENT>bl_mode = '<STR_LIT>'<EOL><DEDENT>self.logger("<STR_LIT>"%(max_bl, bl_mode),<NUM_LIT:1>)<EOL>self.branch_length_mode = bl_mode<EOL><DEDENT>else:<EOL><INDENT>self.branch_length_mode = '<STR_LIT:input>'<EOL><DEDENT>

if branch_length mode is not explicitly set, set according to
empirical branch length distribution in input tree

Parameters
----------

 branch_length_mode : str, 'input', 'joint', 'marginal'
    if the maximal branch length in the tree is longer than 0.05, this will
    default to 'input'. Otherwise set to 'joint'


def clock_filter(self, reroot='<STR_LIT>', n_iqd=None, plot=False):

if n_iqd is None:<EOL><INDENT>n_iqd = ttconf.NIQD<EOL><DEDENT>if type(reroot) is list and len(reroot)==<NUM_LIT:1>:<EOL><INDENT>reroot=str(reroot[<NUM_LIT:0>])<EOL><DEDENT>terminals = self.tree.get_terminals()<EOL>if reroot:<EOL><INDENT>if self.reroot(root='<STR_LIT>' if reroot=='<STR_LIT>' else reroot, covariation=False)==ttconf.ERROR:<EOL><INDENT>return ttconf.ERROR<EOL><DEDENT><DEDENT>else:<EOL><INDENT>self.get_clock_model(covariation=False)<EOL><DEDENT>clock_rate = self.clock_model['<STR_LIT>']<EOL>icpt = self.clock_model['<STR_LIT>']<EOL>res = {}<EOL>for node in terminals:<EOL><INDENT>if hasattr(node, '<STR_LIT>') and  (node.raw_date_constraint is not None):<EOL><INDENT>res[node] = node.dist2root - clock_rate*np.mean(node.raw_date_constraint) - icpt<EOL><DEDENT><DEDENT>residuals = np.array(list(res.values()))<EOL>iqd = np.percentile(residuals,<NUM_LIT>) - np.percentile(residuals,<NUM_LIT>)<EOL>for node,r in res.items():<EOL><INDENT>if abs(r)>n_iqd*iqd and node.up.up is not None:<EOL><INDENT>self.logger('<STR_LIT>'%(node.name,r/iqd), <NUM_LIT:3>, warn=True)<EOL>node.bad_branch=True<EOL><DEDENT>else:<EOL><INDENT>node.bad_branch=False<EOL><DEDENT><DEDENT>if reroot and self.reroot(root=reroot)==ttconf.ERROR:<EOL><INDENT>return ttconf.ERROR<EOL><DEDENT>if plot:<EOL><INDENT>self.plot_root_to_tip()<EOL><DEDENT>return ttconf.SUCCESS<EOL>

Labels outlier branches that don't seem to follow a molecular clock
and excludes them from subsequent molecular clock estimation and
the timetree propagation.

Parameters
----------
 reroot : str
    Method to find the best root in the tree (see :py:meth:`treetime.TreeTime.reroot` for options)

 n_iqd : int
    Number of iqd intervals. The outlier nodes are those which do not fall
    into :math:`IQD\cdot n_iqd` interval (:math:`IQD` is the interval between
    75\ :sup:`th` and 25\ :sup:`th` percentiles)

    If None, the default (3) assumed

 plot : bool
    If True, plot the results


def plot_root_to_tip(self, add_internal=False, label=True, ax=None):

Treg = self.setup_TreeRegression()<EOL>if self.clock_model and '<STR_LIT>' in self.clock_model:<EOL><INDENT>cf = self.clock_model['<STR_LIT>']<EOL><DEDENT>else:<EOL><INDENT>cf = False<EOL><DEDENT>Treg.clock_plot(ax=ax, add_internal=add_internal, confidence=cf, n_sigma=<NUM_LIT:2>,<EOL>regression=self.clock_model)<EOL>

Plot root-to-tip regression

Parameters
----------
add_internal : bool
   If true, plot inte`rnal node positions

label : bool
   If true, label the plots

ax : matplotlib axes
   If not None, use the provided matplotlib axes to plot the results


def reroot(self, root='<STR_LIT>', force_positive=True, covariation=None):

if type(root) is list and len(root)==<NUM_LIT:1>:<EOL><INDENT>root=str(root[<NUM_LIT:0>])<EOL><DEDENT>if root=='<STR_LIT>':<EOL><INDENT>root='<STR_LIT>'<EOL><DEDENT>use_cov = self.use_covariation if covariation is None else covariation<EOL>self.logger("<STR_LIT>"%root,<NUM_LIT:0>)<EOL>for n in self.tree.find_clades():<EOL><INDENT>n.branch_length=n.mutation_length<EOL><DEDENT>if (type(root) is str) and(root in rerooting_mechanisms or root in deprecated_rerooting_mechanisms):<EOL><INDENT>if root in deprecated_rerooting_mechanisms:<EOL><INDENT>if "<STR_LIT>" in root:<EOL><INDENT>use_cov=True<EOL><DEDENT>self.logger('<STR_LIT>'<EOL>%(root, deprecated_rerooting_mechanisms[root]), <NUM_LIT:1>, warn=True)<EOL>root = deprecated_rerooting_mechanisms[root]<EOL><DEDENT>self.logger("<STR_LIT>"%("<STR_LIT>" if use_cov else "<STR_LIT:ignore>"),<NUM_LIT:0>)<EOL>new_root = self._find_best_root(covariation=use_cov,<EOL>slope = <NUM_LIT:0.0> if root.startswith('<STR_LIT>') else None,<EOL>force_positive=force_positive and (not root.startswith('<STR_LIT>')))<EOL><DEDENT>else:<EOL><INDENT>if isinstance(root,Phylo.BaseTree.Clade):<EOL><INDENT>new_root = root<EOL><DEDENT>elif isinstance(root, list):<EOL><INDENT>new_root = self.tree.common_ancestor(*root)<EOL><DEDENT>elif root in self._leaves_lookup:<EOL><INDENT>new_root = self._leaves_lookup[root]<EOL><DEDENT>elif root=='<STR_LIT>':<EOL><INDENT>new_root = sorted([n for n in self.tree.get_terminals()<EOL>if n.raw_date_constraint is not None],<EOL>key=lambda x:np.mean(x.raw_date_constraint))[<NUM_LIT:0>]<EOL><DEDENT>else:<EOL><INDENT>self.logger('<STR_LIT>',<NUM_LIT:0>,warn=True)<EOL>return ttconf.ERROR<EOL><DEDENT>self.tree.root_with_outgroup(new_root, outgroup_branch_length=new_root.branch_length/<NUM_LIT:2>)<EOL>self.get_clock_model(covariation=use_cov)<EOL><DEDENT>if new_root == ttconf.ERROR:<EOL><INDENT>return ttconf.ERROR<EOL><DEDENT>self.logger("<STR_LIT>"<EOL>+('<STR_LIT>' if new_root.name is None else new_root.name), <NUM_LIT:2>)<EOL>self.tree.root.branch_length = self.one_mutation<EOL>self.tree.root.clock_length = self.one_mutation<EOL>self.tree.root.raw_date_constraint = None<EOL>if hasattr(new_root, '<STR_LIT>'):<EOL><INDENT>self.tree.root.time_before_present = new_root.time_before_present<EOL><DEDENT>if hasattr(new_root, '<STR_LIT>'):<EOL><INDENT>self.tree.root.numdate = new_root.numdate<EOL><DEDENT>if not hasattr(self.tree.root, '<STR_LIT>'):<EOL><INDENT>self.tree.root.gamma = <NUM_LIT:1.0><EOL><DEDENT>for n in self.tree.find_clades():<EOL><INDENT>n.mutation_length = n.branch_length<EOL>if not hasattr(n, '<STR_LIT>'):<EOL><INDENT>n.clock_length = n.branch_length<EOL><DEDENT><DEDENT>self.prepare_tree()<EOL>self.get_clock_model(covariation=self.use_covariation)<EOL>return ttconf.SUCCESS<EOL>

Find best root and re-root the tree to the new root

Parameters
----------

 root : str
    Which method should be used to find the best root. Available methods are:

    :code:`best`, `least-squares` - minimize squared residual or likelihood of root-to-tip regression

    :code:`min_dev` - minimize variation of root-to-tip distance

    :code:`oldest` - reroot on the oldest node

    :code:`<node_name>` - reroot to the node with name :code:`<node_name>`

    :code:`[<node_name1>, <node_name2>, ...]` - reroot to the MRCA of these nodes

  force_positive : bool
    only consider positive rates when searching for the optimal root

  covariation : bool
     account for covariation in root-to-tip regression


self.logger("<STR_LIT>",<NUM_LIT:1>)<EOL>poly_found=<NUM_LIT:0><EOL>for n in self.tree.find_clades():<EOL><INDENT>if len(n.clades) > <NUM_LIT:2>:<EOL><INDENT>prior_n_clades = len(n.clades)<EOL>self._poly(n, merge_compressed)<EOL>poly_found+=prior_n_clades - len(n.clades)<EOL><DEDENT><DEDENT>obsolete_nodes = [n for n in self.tree.find_clades() if len(n.clades)==<NUM_LIT:1> and n.up is not None]<EOL>for node in obsolete_nodes:<EOL><INDENT>self.logger('<STR_LIT>'+node.name,<NUM_LIT:4>)<EOL>if node.up is not None:<EOL><INDENT>self.tree.collapse(node)<EOL><DEDENT><DEDENT>if poly_found:<EOL><INDENT>self.logger('<STR_LIT>'%poly_found,<NUM_LIT:3>)<EOL><DEDENT>else:<EOL><INDENT>self.logger('<STR_LIT>',<NUM_LIT:3>)<EOL><DEDENT>return poly_found<EOL>

Resolve the polytomies on the tree.

The function scans the tree, resolves polytomies if present,
and re-optimizes the tree with new topology. Note that polytomies are only
resolved if that would result in higher likelihood. Sometimes, stretching
two or more branches that carry several mutations is less costly than
an additional branch with zero mutations (long branches are not stiff,
short branches are).

Parameters
----------
 merge_compressed : bool
    If True, keep compressed branches as polytomies. If False,
    return a strictly binary tree.

Returns
--------
 poly_found : int
    The number of polytomies found


def _poly(self, clade, merge_compressed):

from .branch_len_interpolator import BranchLenInterpolator<EOL>zero_branch_slope = self.gtr.mu*self.seq_len<EOL>def _c_gain(t, n1, n2, parent):<EOL><INDENT>"""<STR_LIT>"""<EOL>cg2 = n2.branch_length_interpolator(parent.time_before_present - n2.time_before_present) - n2.branch_length_interpolator(t - n2.time_before_present)<EOL>cg1 = n1.branch_length_interpolator(parent.time_before_present - n1.time_before_present) - n1.branch_length_interpolator(t - n1.time_before_present)<EOL>cg_new = - zero_branch_slope * (parent.time_before_present - t) <EOL>return -(cg2+cg1+cg_new)<EOL><DEDENT>def cost_gain(n1, n2, parent):<EOL><INDENT>"""<STR_LIT>"""<EOL>try:<EOL><INDENT>cg = sciopt.minimize_scalar(_c_gain,<EOL>bounds=[max(n1.time_before_present,n2.time_before_present), parent.time_before_present],<EOL>method='<STR_LIT>',args=(n1,n2, parent))<EOL>return cg['<STR_LIT:x>'], - cg['<STR_LIT>']<EOL><DEDENT>except:<EOL><INDENT>self.logger("<STR_LIT>", <NUM_LIT:3>, warn=True)<EOL>return parent.time_before_present, <NUM_LIT:0.0><EOL><DEDENT><DEDENT>def merge_nodes(source_arr, isall=False):<EOL><INDENT>mergers = np.array([[cost_gain(n1,n2, clade) if i1<i2 else (<NUM_LIT:0.0>,-<NUM_LIT:1.0>)<EOL>for i1,n1 in enumerate(source_arr)]<EOL>for i2, n2 in enumerate(source_arr)])<EOL>LH = <NUM_LIT:0><EOL>while len(source_arr) > <NUM_LIT:1> + int(isall):<EOL><INDENT>new_positions = mergers[:,:,<NUM_LIT:0>]<EOL>cost_gains = mergers[:,:,<NUM_LIT:1>]<EOL>np.fill_diagonal(cost_gains, -<NUM_LIT>)<EOL>idxs = np.unravel_index(cost_gains.argmax(),cost_gains.shape)<EOL>if (idxs[<NUM_LIT:0>] == idxs[<NUM_LIT:1>]) or cost_gains.max()<<NUM_LIT:0>:<EOL><INDENT>self.logger("<STR_LIT>"+clade.name,<NUM_LIT:4>)<EOL>return LH<EOL><DEDENT>n1, n2 = source_arr[idxs[<NUM_LIT:0>]], source_arr[idxs[<NUM_LIT:1>]]<EOL>LH += cost_gains[idxs]<EOL>new_node = Phylo.BaseTree.Clade()<EOL>new_node.time_before_present = new_positions[idxs]<EOL>new_node.branch_length = clade.time_before_present - new_node.time_before_present<EOL>new_node.clades = [n1,n2]<EOL>n1.branch_length = new_node.time_before_present - n1.time_before_present<EOL>n2.branch_length = new_node.time_before_present - n2.time_before_present<EOL>new_node.up = clade<EOL>n1.up = new_node<EOL>n2.up = new_node<EOL>if hasattr(clade, "<STR_LIT>"):<EOL><INDENT>new_node.cseq = clade.cseq<EOL>self._store_compressed_sequence_to_node(new_node)<EOL><DEDENT>new_node.mutations = []<EOL>new_node.mutation_length = <NUM_LIT:0.0><EOL>new_node.branch_length_interpolator = BranchLenInterpolator(new_node, self.gtr, one_mutation=self.one_mutation,<EOL>branch_length_mode = self.branch_length_mode)<EOL>clade.clades.remove(n1)<EOL>clade.clades.remove(n2)<EOL>clade.clades.append(new_node)<EOL>self.logger('<STR_LIT>'+clade.name,<NUM_LIT:3>)<EOL>self.logger("<STR_LIT>" + str(cost_gains[idxs].round(<NUM_LIT:3>)), <NUM_LIT:3>)<EOL>if len(source_arr)><NUM_LIT:2>: <EOL><INDENT>for ii in np.sort(idxs)[::-<NUM_LIT:1>]:<EOL><INDENT>tmp_ind = np.arange(mergers.shape[<NUM_LIT:0>])!=ii<EOL>mergers = mergers[tmp_ind].swapaxes(<NUM_LIT:0>,<NUM_LIT:1>)<EOL>mergers = mergers[tmp_ind].swapaxes(<NUM_LIT:0>,<NUM_LIT:1>)<EOL><DEDENT>source_arr.remove(n1)<EOL>source_arr.remove(n2)<EOL>new_gains = np.array([[cost_gain(n1,new_node, clade) for n1 in source_arr]])<EOL>mergers = np.vstack((mergers, new_gains)).swapaxes(<NUM_LIT:0>,<NUM_LIT:1>)<EOL>source_arr.append(new_node)<EOL>new_gains = np.array([[cost_gain(n1,new_node, clade) for n1 in source_arr]])<EOL>mergers = np.vstack((mergers, new_gains)).swapaxes(<NUM_LIT:0>,<NUM_LIT:1>)<EOL><DEDENT>else: <EOL><INDENT>source_arr.remove(n1)<EOL>source_arr.remove(n2)<EOL>source_arr.append(new_node)<EOL>mergers = np.array([[cost_gain(n1,n2, clade) for n1 in source_arr]<EOL>for n2 in source_arr])<EOL><DEDENT><DEDENT>return LH<EOL><DEDENT>stretched = [c for c  in clade.clades if c.mutation_length < c.clock_length]<EOL>compressed = [c for c in clade.clades if c not in stretched]<EOL>if len(stretched)==<NUM_LIT:1> and merge_compressed is False:<EOL><INDENT>return <NUM_LIT:0.0><EOL><DEDENT>LH = merge_nodes(stretched, isall=len(stretched)==len(clade.clades))<EOL>if merge_compressed and len(compressed)><NUM_LIT:1>:<EOL><INDENT>LH += merge_nodes(compressed, isall=len(compressed)==len(clade.clades))<EOL><DEDENT>return LH<EOL>

Function to resolve polytomies for a given parent node. If the
number of the direct decendants is less than three (not a polytomy), does
nothing. Otherwise, for each pair of nodes, assess the possible LH increase
which could be gained by merging the two nodes. The increase in the LH is
basically the tradeoff between the gain of the LH due to the changing the
branch lenghts towards the optimal values and the decrease due to the
introduction of the new branch with zero optimal length.


try:<EOL><INDENT>u_lh = self.tree.unconstrained_sequence_LH<EOL>if joint:<EOL><INDENT>s_lh = self.tree.sequence_joint_LH<EOL>t_lh = self.tree.positional_joint_LH<EOL>c_lh = self.tree.coalescent_joint_LH<EOL><DEDENT>else:<EOL><INDENT>s_lh = self.tree.sequence_marginal_LH<EOL>t_lh = self.tree.positional_marginal_LH<EOL>c_lh = <NUM_LIT:0><EOL><DEDENT>print ("<STR_LIT>"<EOL>"<STR_LIT>"<EOL>"<STR_LIT>"<EOL>"<STR_LIT>"<EOL>"<STR_LIT>"<EOL>"<STR_LIT>"%(u_lh, s_lh,t_lh, c_lh))<EOL><DEDENT>except:<EOL><INDENT>print("<STR_LIT>")<EOL><DEDENT>

Print the total likelihood of the tree given the constrained leaves

Parameters
----------

 joint : bool
    If true, print joint LH, else print marginal LH


def add_coalescent_model(self, Tc, **kwargs):

from .merger_models import Coalescent<EOL>self.logger('<STR_LIT>'+str(Tc),<NUM_LIT:1>)<EOL>self.merger_model = Coalescent(self.tree,<EOL>date2dist=self.date2dist, logger=self.logger)<EOL>if Tc=='<STR_LIT>': <EOL><INDENT>self.merger_model.optimize_skyline(**kwargs)<EOL>self.logger("<STR_LIT>", <NUM_LIT:2>)<EOL><DEDENT>else:<EOL><INDENT>if Tc in ['<STR_LIT>', '<STR_LIT>']:<EOL><INDENT>self.merger_model.optimize_Tc()<EOL>self.logger("<STR_LIT>"%self.merger_model.Tc.y[<NUM_LIT:0>], <NUM_LIT:2>)<EOL><DEDENT>else:<EOL><INDENT>try:<EOL><INDENT>self.merger_model.set_Tc(Tc)<EOL><DEDENT>except:<EOL><INDENT>self.logger("<STR_LIT>", <NUM_LIT:1>, warn=True)<EOL><DEDENT><DEDENT><DEDENT>self.merger_model.attach_to_tree()<EOL>

Add a coalescent model to the tree and optionally optimze

        Parameters
        ----------
        Tc : float,str
            If this is a float, it will be interpreted as the inverse merger
            rate in molecular clock units, if its is a


def relaxed_clock(self, slack=None, coupling=None, **kwargs):

if slack is None: slack=ttconf.MU_ALPHA<EOL>if coupling is None: coupling=ttconf.MU_BETA<EOL>self.logger("<STR_LIT>"%(slack, coupling),<NUM_LIT:2>)<EOL>c=<NUM_LIT:1.0>/self.one_mutation<EOL>for node in self.tree.find_clades(order='<STR_LIT>'):<EOL><INDENT>opt_len = node.mutation_length<EOL>act_len = node.clock_length if hasattr(node, '<STR_LIT>') else node.branch_length<EOL>node._k2 = slack + c*act_len**<NUM_LIT:2>/(opt_len+self.one_mutation)<EOL>node._k1 = -<NUM_LIT:2>*(c*act_len*opt_len/(opt_len+self.one_mutation) + slack)<EOL>for child in node.clades:<EOL><INDENT>denom = coupling+child._k2<EOL>node._k2 += coupling*(<NUM_LIT:1.0>-coupling/denom)**<NUM_LIT:2> + child._k2*coupling**<NUM_LIT:2>/denom**<NUM_LIT:2><EOL>node._k1 += (coupling*(<NUM_LIT:1.0>-coupling/denom)*child._k1/denom- coupling*child._k1*child._k2/denom**<NUM_LIT:2>+ coupling*child._k1/denom)<EOL><DEDENT><DEDENT>for node in self.tree.find_clades(order='<STR_LIT>'):<EOL><INDENT>if node.up is None:<EOL><INDENT>node.gamma = max(<NUM_LIT:0.1>, -<NUM_LIT:0.5>*node._k1/node._k2)<EOL><DEDENT>else:<EOL><INDENT>if node.up.up is None:<EOL><INDENT>g_up = node.up.gamma<EOL><DEDENT>else:<EOL><INDENT>g_up = node.up.branch_length_interpolator.gamma<EOL><DEDENT>node.branch_length_interpolator.gamma = max(<NUM_LIT:0.1>,(coupling*g_up - <NUM_LIT:0.5>*node._k1)/(coupling+node._k2))<EOL><DEDENT><DEDENT>

Allow the mutation rate to vary on the tree (relaxed molecular clock).
Changes of the mutation rates from one branch to another are penalized.
In addition, deviation of the mutation rate from the mean rate is
penalized.

Parameters
----------
 slack : float
    Maximum change in substitution rate between parent and child nodes

 coupling : float
    Maximum difference in substitution rates in sibling nodes


def _find_best_root(self, covariation=True, force_positive=True, slope=<NUM_LIT:0>, **kwarks):

for n in self.tree.find_clades():<EOL><INDENT>n.branch_length=n.mutation_length<EOL><DEDENT>self.logger("<STR_LIT>",<NUM_LIT:2>)<EOL>Treg = self.setup_TreeRegression(covariation=covariation)<EOL>return Treg.optimal_reroot(force_positive=force_positive, slope=slope)['<STR_LIT>']<EOL>

Determine the node that, when the tree is rooted on this node, results
in the best regression of temporal constraints and root to tip distances.

Parameters
----------

 infer_gtr : bool
    If True, infer new GTR model after re-root

 covariation : bool
    account for covariation structure when rerooting the tree

 force_positive : bool
    only accept positive evolutionary rate estimates when rerooting the tree


<EOL>sequences = defaultdict(dict)<EOL>insertions = defaultdict(dict) <EOL>def getAmbigCode(bp1, bp2, bp3="<STR_LIT>"):<EOL><INDENT>bps = [bp1,bp2,bp3]<EOL>bps.sort()<EOL>key = "<STR_LIT>".join(bps)<EOL>return {<EOL>'<STR_LIT>': '<STR_LIT:Y>',<EOL>'<STR_LIT>': '<STR_LIT:R>',<EOL>'<STR_LIT>': '<STR_LIT>',<EOL>'<STR_LIT>': '<STR_LIT:S>',<EOL>'<STR_LIT>': '<STR_LIT>',<EOL>'<STR_LIT>': '<STR_LIT:M>',<EOL>'<STR_LIT>': '<STR_LIT:D>',<EOL>'<STR_LIT>': '<STR_LIT>',<EOL>'<STR_LIT>': '<STR_LIT:H>',<EOL>'<STR_LIT>': '<STR_LIT:B>'<EOL>}[key]<EOL><DEDENT>def parseCall(snps, ins, pos, ref, alt):<EOL><INDENT>if len(ref) > <NUM_LIT:1> and len(alt)>len(ref):<EOL><INDENT>for i in range(len(ref)):<EOL><INDENT>if ref[i] != alt[i]:<EOL><INDENT>snps[pos+i] = alt[i] if alt[i] != '<STR_LIT:.>' else '<STR_LIT:N>' <EOL><DEDENT>if (i+<NUM_LIT:1>) >= len(ref):<EOL><INDENT>ins[pos+i] = alt[i:]<EOL><DEDENT><DEDENT><DEDENT>elif len(ref) > <NUM_LIT:1>:<EOL><INDENT>for i in range(len(ref)):<EOL><INDENT>if i+<NUM_LIT:1> > len(alt):<EOL><INDENT>snps[pos+i] = '<STR_LIT:->'<EOL><DEDENT>else:<EOL><INDENT>if ref[i] != alt[i]:<EOL><INDENT>snps[pos+i] = alt[i] if alt[i] != '<STR_LIT:.>' else '<STR_LIT:N>' <EOL><DEDENT><DEDENT><DEDENT><DEDENT>elif len(alt) > <NUM_LIT:1>:<EOL><INDENT>ins[pos] = alt<EOL><DEDENT>else:<EOL><INDENT>snps[pos] = alt<EOL><DEDENT><DEDENT>def parseBadCall(snps, ins, pos, ref, ALT):<EOL><INDENT>if len(ref) > <NUM_LIT:1>:<EOL><INDENT>if gen[<NUM_LIT:0>] == '<STR_LIT:0>' or gen[<NUM_LIT:0>] == '<STR_LIT:.>':<EOL><INDENT>if gen[<NUM_LIT:0>] == '<STR_LIT:0>':   <EOL><INDENT>alt = str(ALT[int(gen[<NUM_LIT:2>])-<NUM_LIT:1>])<EOL><DEDENT>else: <EOL><INDENT>alt = ref[<NUM_LIT:0>]<EOL><DEDENT>for i in range(len(ref)):<EOL><INDENT>if i+<NUM_LIT:1> > len(alt):<EOL><INDENT>snps[pos+i] = '<STR_LIT:N>'<EOL><DEDENT>else:<EOL><INDENT>if ref[i] != alt[i]:<EOL><INDENT>snps[pos+i] = alt[i] if alt[i] != '<STR_LIT:.>' else '<STR_LIT:N>' <EOL><DEDENT><DEDENT><DEDENT><DEDENT><DEDENT>elif gen[<NUM_LIT:0>] == '<STR_LIT:0>':<EOL><INDENT>alt = str(ALT[int(gen[<NUM_LIT:2>])-<NUM_LIT:1>])<EOL>if len(alt)==<NUM_LIT:1>:<EOL><INDENT>alt = '<STR_LIT:N>' <EOL>snps[pos] = alt<EOL><DEDENT><DEDENT>elif len(ALT)==len("<STR_LIT>".join(ALT)):<EOL><INDENT>alt = '<STR_LIT:N>'<EOL>snps[pos] = alt<EOL><DEDENT><DEDENT>import gzip<EOL>from Bio import SeqIO<EOL>import numpy as np<EOL>nsamp = <NUM_LIT:0><EOL>posLoc = <NUM_LIT:0><EOL>refLoc = <NUM_LIT:0><EOL>altLoc = <NUM_LIT:0><EOL>sampLoc = <NUM_LIT:9><EOL>opn = gzip.open if vcf_file.endswith(('<STR_LIT>', '<STR_LIT>')) else open<EOL>with opn(vcf_file, mode='<STR_LIT>') as f:<EOL><INDENT>for line in f:<EOL><INDENT>if line[<NUM_LIT:0>] != '<STR_LIT:#>':<EOL><INDENT>line = line.strip()<EOL>dat = line.split('<STR_LIT:\t>')<EOL>POS = int(dat[posLoc])<EOL>REF = dat[refLoc]<EOL>ALT = dat[altLoc].split('<STR_LIT:U+002C>')<EOL>calls = np.array(dat[sampLoc:])<EOL>recCalls = {}<EOL>for sname, sa in zip(samps, calls):<EOL><INDENT>if '<STR_LIT::>' in sa: <EOL><INDENT>gt = sa.split('<STR_LIT::>')[<NUM_LIT:0>]<EOL><DEDENT>else: <EOL><INDENT>gt = sa<EOL><DEDENT>if gt == '<STR_LIT:0>' or gt == '<STR_LIT:1>': <EOL><INDENT>gt = '<STR_LIT>' if gt == '<STR_LIT:0>' else '<STR_LIT>'<EOL><DEDENT>if ('<STR_LIT:/>' in gt and gt != '<STR_LIT>') or ('<STR_LIT:|>' in gt and gt != '<STR_LIT>'):<EOL><INDENT>recCalls[sname] = gt<EOL><DEDENT><DEDENT>for seq, gen in recCalls.items():<EOL><INDENT>ref = REF<EOL>pos = POS-<NUM_LIT:1>     <EOL>if gen[<NUM_LIT:0>] != '<STR_LIT:0>' and gen[<NUM_LIT:2>] != '<STR_LIT:0>' and gen[<NUM_LIT:0>] != '<STR_LIT:.>' and gen[<NUM_LIT:2>] != '<STR_LIT:.>':<EOL><INDENT>alt = str(ALT[int(gen[<NUM_LIT:0>])-<NUM_LIT:1>])   <EOL>if seq not in sequences.keys():<EOL><INDENT>sequences[seq] = {}<EOL><DEDENT>parseCall(sequences[seq],insertions[seq], pos, ref, alt)<EOL><DEDENT>else:<EOL><INDENT>parseBadCall(sequences[seq],insertions[seq], pos, ref, ALT)<EOL><DEDENT><DEDENT><DEDENT>elif line[<NUM_LIT:0>] == '<STR_LIT:#>' and line[<NUM_LIT:1>] == '<STR_LIT:C>':<EOL><INDENT>header = line.strip().split('<STR_LIT:\t>')<EOL>posLoc = header.index("<STR_LIT>")<EOL>refLoc = header.index('<STR_LIT>')<EOL>altLoc = header.index('<STR_LIT>')<EOL>sampLoc = header.index('<STR_LIT>')+<NUM_LIT:1><EOL>samps = header[sampLoc:]<EOL>samps = [ x.strip() for x in samps ] <EOL>nsamp = len(samps)<EOL><DEDENT><DEDENT><DEDENT>positions = set()<EOL>for seq, muts in sequences.items():<EOL><INDENT>positions.update(muts.keys())<EOL><DEDENT>if nsamp > len(sequences):<EOL><INDENT>missings = set(samps).difference(sequences.keys())<EOL>for s in missings:<EOL><INDENT>sequences[s] = {}<EOL><DEDENT><DEDENT>refSeq = SeqIO.read(ref_file, format='<STR_LIT>')<EOL>refSeq = refSeq.upper() <EOL>refSeqStr = str(refSeq.seq)<EOL>compress_seq = {'<STR_LIT>':refSeqStr,<EOL>'<STR_LIT>': sequences,<EOL>'<STR_LIT>': insertions,<EOL>'<STR_LIT>': sorted(positions)}<EOL>return compress_seq<EOL>

Reads in a vcf/vcf.gz file and associated
reference sequence fasta (to which the VCF file is mapped).

Parses mutations, insertions, and deletions and stores them in a nested dict,
see 'returns' for the dict structure.

Calls with heterozygous values 0/1, 0/2, etc and no-calls (./.) are
replaced with Ns at the associated sites.

Positions are stored to correspond the location in the reference sequence
in Python (numbering is transformed to start at 0)

Parameters
----------
vcf_file : string
    Path to the vcf or vcf.gz file to be read in
ref_file : string
    Path to the fasta reference file to be read in

Returns
--------
compress_seq : nested dict
    In the format: ::

        {
        'reference':'AGCTCGA..A',
        'sequences': { 'seq1':{4:'A', 7:'-'}, 'seq2':{100:'C'} },
        'insertions': { 'seq1':{4:'ATT'}, 'seq3':{1:'TT', 10:'CAG'} },
        'positions': [1,4,7,10,100...]
        }

    references : string
        String of the reference sequence read from the Fasta, to which
        the variable sites are mapped
    sequences : nested dict
        Dict containing sequence names as keys which map to dicts
        that have position as key and the single-base mutation (or deletion)
        as values
    insertions : nested dict
        Dict in the same format as the above, which stores insertions and their
        locations. The first base of the insertion is the same as whatever is
        currently in that position (Ref if no mutation, mutation in 'sequences'
        otherwise), so the current base can be directly replaced by the bases held here.
    positions : list
        Python list of all positions with a mutation, insertion, or deletion.


<EOL><INDENT>sequences = tree_dict['<STR_LIT>']<EOL>ref = tree_dict['<STR_LIT>']<EOL>positions = tree_dict['<STR_LIT>']<EOL>def handleDeletions(i, pi, pos, ref, delete, pattern):<EOL><INDENT>refb = ref[pi]<EOL>if delete: <EOL><INDENT>i-=<NUM_LIT:1>    <EOL>pi-=<NUM_LIT:1><EOL>pos = pi+<NUM_LIT:1><EOL>refb = ref[pi]<EOL>pattern = []<EOL>for k,v in sequences.items():<EOL><INDENT>try:<EOL><INDENT>pattern.append(sequences[k][pi])<EOL><DEDENT>except KeyError:<EOL><INDENT>pattern.append(ref[pi])<EOL><DEDENT><DEDENT>pattern = np.array(pattern)<EOL><DEDENT>sites = []<EOL>sites.append(pattern)<EOL>while (i+<NUM_LIT:1>) < len(positions) and positions[i+<NUM_LIT:1>] == pi+<NUM_LIT:1>:<EOL><INDENT>i+=<NUM_LIT:1><EOL>pi = positions[i]<EOL>pattern = []<EOL>for k,v in sequences.items():<EOL><INDENT>try:<EOL><INDENT>pattern.append(sequences[k][pi])<EOL><DEDENT>except KeyError:<EOL><INDENT>pattern.append(ref[pi])<EOL><DEDENT><DEDENT>pattern = np.array(pattern)<EOL>if any(pattern == '<STR_LIT:->'): <EOL><INDENT>sites.append(pattern)<EOL>refb = refb+ref[pi]<EOL><DEDENT>else: <EOL><INDENT>i-=<NUM_LIT:1>    <EOL><DEDENT><DEDENT>sites = np.asarray(sites)<EOL>align = np.rot90(sites)<EOL>align = np.flipud(align)<EOL>fullpat = []<EOL>for pt in align:<EOL><INDENT>gp = len(pt)-<NUM_LIT:1><EOL>while pt[gp] == '<STR_LIT:->':<EOL><INDENT>pt[gp] = '<STR_LIT>'<EOL>gp-=<NUM_LIT:1><EOL><DEDENT>pat = "<STR_LIT>".join(pt)<EOL>if pat == refb:<EOL><INDENT>fullpat.append('<STR_LIT:.>')<EOL><DEDENT>else:<EOL><INDENT>fullpat.append(pat)<EOL><DEDENT><DEDENT>pattern = np.array(fullpat)<EOL>return i, pi, pos, refb, pattern<EOL><DEDENT>header=["<STR_LIT>","<STR_LIT>","<STR_LIT>","<STR_LIT>","<STR_LIT>","<STR_LIT>","<STR_LIT>","<STR_LIT>","<STR_LIT>"]+list(sequences.keys())<EOL>with open(file_name, '<STR_LIT:w>') as the_file:<EOL><INDENT>the_file.write( "<STR_LIT>"+<EOL>"<STR_LIT>"+<EOL>"<STR_LIT>")<EOL>the_file.write("<STR_LIT:\t>".join(header)+"<STR_LIT:\n>")<EOL><DEDENT>vcfWrite = []<EOL>errorPositions = []<EOL>explainedErrors = <NUM_LIT:0><EOL>i=<NUM_LIT:0><EOL>while i < len(positions):<EOL><INDENT>pi = positions[i]<EOL>pos = pi+<NUM_LIT:1> <EOL>refb = ref[pi] <EOL>delete = False <EOL>deleteGroup = False <EOL>pattern = []<EOL>pattern2 = []<EOL>for k,v in sequences.items():<EOL><INDENT>try:<EOL><INDENT>pattern.append(sequences[k][pi])<EOL><DEDENT>except KeyError:<EOL><INDENT>pattern.append(ref[pi])<EOL><DEDENT>try:<EOL><INDENT>pattern2.append(sequences[k][pi+<NUM_LIT:1>])<EOL><DEDENT>except KeyError:<EOL><INDENT>pattern2.append(ref[pi+<NUM_LIT:1>])<EOL><DEDENT><DEDENT>pattern = np.array(pattern)<EOL>pattern2 = np.array(pattern2)<EOL>if any(pattern == '<STR_LIT:->'):<EOL><INDENT>if pos != <NUM_LIT:1>:<EOL><INDENT>deleteGroup = True<EOL>delete = True<EOL><DEDENT>else:<EOL><INDENT>print ("<STR_LIT>")<EOL><DEDENT><DEDENT>else:<EOL><INDENT>if any(pattern2 == '<STR_LIT:->'):<EOL><INDENT>deleteGroup = True<EOL><DEDENT><DEDENT>if delete or deleteGroup:<EOL><INDENT>i, pi, pos, refb, pattern = handleDeletions(i, pi, pos, ref, delete, pattern)<EOL><DEDENT>else:<EOL><INDENT>pattern[pattern==refb] = '<STR_LIT:.>'<EOL><DEDENT>uniques = np.unique(pattern)<EOL>uniques = uniques[np.where(uniques!='<STR_LIT:.>')]<EOL>j=<NUM_LIT:1><EOL>for u in uniques:<EOL><INDENT>pattern[np.where(pattern==u)[<NUM_LIT:0>]] = str(j)<EOL>j+=<NUM_LIT:1><EOL><DEDENT>calls = [ j+"<STR_LIT:/>"+j if j!='<STR_LIT:.>' else '<STR_LIT:.>' for j in pattern ]<EOL>printPos = True<EOL>if len(uniques)==<NUM_LIT:0>:<EOL><INDENT>if '<STR_LIT>' in tree_dict and pi in tree_dict['<STR_LIT>']:<EOL><INDENT>explainedErrors += <NUM_LIT:1><EOL>printPos = False <EOL><DEDENT>else:<EOL><INDENT>errorPositions.append(str(pi))<EOL><DEDENT><DEDENT>if printPos:<EOL><INDENT>output = ["<STR_LIT>", str(pos), "<STR_LIT:.>", refb, "<STR_LIT:U+002C>".join(uniques), "<STR_LIT:.>", "<STR_LIT>", "<STR_LIT:.>", "<STR_LIT>"] + calls<EOL>vcfWrite.append("<STR_LIT:\t>".join(output))<EOL><DEDENT>i+=<NUM_LIT:1><EOL><DEDENT>if '<STR_LIT>' in tree_dict and explainedErrors != <NUM_LIT:0>:<EOL><INDENT>print ( "<STR_LIT>".format(explainedErrors))<EOL><DEDENT>if len(errorPositions) != <NUM_LIT:0>:<EOL><INDENT>print ("<STR_LIT>"<EOL>"<STR_LIT>"<EOL>"<STR_LIT>"<EOL>"<STR_LIT>"<EOL>"<STR_LIT>"<EOL>"<STR_LIT>"<EOL>"<STR_LIT>"<EOL>"<STR_LIT>"<EOL>"<STR_LIT>".format(str(len(errorPositions))))<EOL>print ("<STR_LIT:U+002C>".join(errorPositions))<EOL><DEDENT>with open(file_name, '<STR_LIT:a>') as the_file:<EOL><INDENT>the_file.write("<STR_LIT:\n>".join(vcfWrite))<EOL><DEDENT>if file_name.endswith(('<STR_LIT>', '<STR_LIT>')):<EOL><INDENT>import os<EOL>os.rename(file_name, file_name[:-<NUM_LIT:3>])<EOL>call = ["<STR_LIT>", file_name[:-<NUM_LIT:3>]]<EOL>os.system("<STR_LIT:U+0020>".join(call))<EOL><DEDENT><DEDENT>

Writes out a VCF-style file (which seems to be minimally handleable
by vcftools and pyvcf) of the alignment. This is created from a dict
in a similar format to what's created by :py:meth:`treetime.vcf_utils.read_vcf`

Positions of variable sites are transformed to start at 1 to match
VCF convention.

Parameters
----------
 tree_dict: nested dict
    A nested dict with keys 'sequence' 'reference' and 'positions',
    as is created by :py:meth:`treetime.TreeAnc.get_tree_dict`

 file_name: str
    File to which the new VCF should be written out. File names ending with
    '.gz' will result in the VCF automatically being gzipped.


pass<EOL>

No-op predefined module level logging callback.

    Args:
        output_string (str): string to output.


Simple print predefined module level logging callback.

    Args:
        output_string (str): string to output.

    Returns:


global ekmmeters_log_func<EOL>ekmmeters_log_func = function_name<EOL>pass<EOL>

Set predefined or user-defined module level log output function.

    Args:
        function_name (function):  function taking 1 string returning nothing.


if priority <= ekmmeters_log_level:<EOL><INDENT>dt = datetime.datetime<EOL>stamp = datetime.datetime.now().strftime("<STR_LIT>")<EOL>ekmmeters_log_func("<STR_LIT>" + stamp + "<STR_LIT>" + logstr)<EOL><DEDENT>pass<EOL>

Send string to module level log

    Args:
        logstr (str): string to print.
        priority (int): priority, supports 3 (default) and 4 (special).


global ekmmeters_log_level<EOL>ekmmeters_log_level = level<EOL>pass<EOL>

Set the logging level.
    Args:
        level (int): cutoff level (print at level and below).


def __init__(self, ttyport, baudrate=<NUM_LIT>, force_wait = <NUM_LIT:0.1>):

self.m_ttyport = ttyport<EOL>self.m_baudrate = baudrate<EOL>self.m_ser = None<EOL>self.m_fd = None<EOL>self.m_max_waits = <NUM_LIT:100><EOL>self.m_wait_sleep = <NUM_LIT><EOL>self.m_force_wait = force_wait<EOL>self.m_init_wait = <NUM_LIT><EOL>pass<EOL>

Args:
    ttyport (str): port name, ex 'COM3' '/dev/ttyUSB0'
    baudrate (int): optional, 9600 default and recommended
    force_wait(float) : optional post commnd sleep, if required


try:<EOL><INDENT>self.m_ser = serial.Serial(port=self.m_ttyport,<EOL>baudrate=self.m_baudrate,<EOL>timeout=<NUM_LIT:0>,<EOL>parity=serial.PARITY_EVEN,<EOL>stopbits=serial.STOPBITS_ONE,<EOL>bytesize=serial.SEVENBITS,<EOL>rtscts=False)<EOL>ekm_log("<STR_LIT>" + serial.VERSION)<EOL>ekm_log("<STR_LIT>" + self.m_ttyport)<EOL>ekm_log("<STR_LIT>" + str(self.m_baudrate))<EOL>time.sleep(self.m_init_wait)<EOL>return True<EOL><DEDENT>except:<EOL><INDENT>ekm_log(traceback.format_exc(sys.exc_info()))<EOL><DEDENT>return False<EOL>

Required initialization call, wraps pyserial constructor.


return self.m_ttyport<EOL>

Getter for serial port name

        Returns:
            string: name of serial port (ex: 'COM3', '/dev/ttyS0')


view_str = output.encode('<STR_LIT:ascii>', '<STR_LIT:ignore>')<EOL>if (len(view_str) > <NUM_LIT:0>):<EOL><INDENT>self.m_ser.write(view_str)<EOL>self.m_ser.flush()<EOL>self.m_ser.reset_input_buffer()<EOL>time.sleep(self.m_force_wait)<EOL><DEDENT>pass<EOL>

Passthrough for pyserial Serial.write().

        Args:
            output (str): Block to write to port


def setPollingValues(self, max_waits, wait_sleep):

self.m_max_waits = max_waits<EOL>self.m_wait_sleep = wait_sleep<EOL>

Optional polling loop control

        Args:
            max_waits (int):   waits
            wait_sleep (int):  ms per wait


waits = <NUM_LIT:0>  <EOL>response_str = "<STR_LIT>"  <EOL>try:<EOL><INDENT>waits = <NUM_LIT:0>  <EOL>while (waits < self.m_max_waits):<EOL><INDENT>bytes_to_read = self.m_ser.inWaiting()<EOL>if bytes_to_read > <NUM_LIT:0>:<EOL><INDENT>next_chunk = str(self.m_ser.read(bytes_to_read)).encode('<STR_LIT:ascii>', '<STR_LIT:ignore>')<EOL>response_str += next_chunk<EOL>if (len(response_str) == <NUM_LIT:255>):<EOL><INDENT>time.sleep(self.m_force_wait)<EOL>return response_str<EOL><DEDENT>if (len(response_str) == <NUM_LIT:1>) and (response_str.encode('<STR_LIT>') == '<STR_LIT>'):<EOL><INDENT>time.sleep(self.m_force_wait)<EOL>return response_str<EOL><DEDENT><DEDENT>else:  <EOL><INDENT>waits += <NUM_LIT:1><EOL>time.sleep(self.m_force_wait)<EOL><DEDENT><DEDENT>response_str = "<STR_LIT>"<EOL><DEDENT>except:<EOL><INDENT>ekm_log(traceback.format_exc(sys.exc_info()))<EOL><DEDENT>return response_str<EOL>

Poll for finished block or first byte ACK.
        Args:
            context (str): internal serial call context.

        Returns:
            string: Response, implict cast from byte array.


self.m_connection_string = connection_string<EOL>self.m_all_fields = SerialBlock()<EOL>self.combineAB()<EOL>pass<EOL>

Args:
    connection_string (str): database appropriate connection string


self.m_connection_string = connection_string<EOL>pass<EOL>

Setter for connection string.
        Args:
            connection_string (str): Connection string.


v4definition_meter = V4Meter()<EOL>v4definition_meter.makeAB()<EOL>defv4 = v4definition_meter.getReadBuffer()<EOL>v3definition_meter = V3Meter()<EOL>v3definition_meter.makeReturnFormat()<EOL>defv3 = v3definition_meter.getReadBuffer()<EOL>for fld in defv3:<EOL><INDENT>if fld not in self.m_all_fields:<EOL><INDENT>compare_fld = fld.upper()<EOL>if not "<STR_LIT>" in compare_fld and not "<STR_LIT>" in compare_fld:<EOL><INDENT>self.m_all_fields[fld] = defv3[fld]<EOL><DEDENT><DEDENT><DEDENT>for fld in defv4:<EOL><INDENT>if fld not in self.m_all_fields:<EOL><INDENT>compare_fld = fld.upper()<EOL>if not "<STR_LIT>" in compare_fld and not "<STR_LIT>" in compare_fld:<EOL><INDENT>self.m_all_fields[fld] = defv4[fld]<EOL><DEDENT><DEDENT><DEDENT>pass<EOL>

Use the serial block definitions in V3 and V4 to create one field list.


if fld_type == FieldType.Float:<EOL><INDENT>return "<STR_LIT>"<EOL><DEDENT>elif fld_type == FieldType.String:<EOL><INDENT>return "<STR_LIT>" + str(fld_len) + "<STR_LIT:)>"<EOL><DEDENT>elif fld_type == FieldType.Int:<EOL><INDENT>return "<STR_LIT>"<EOL><DEDENT>elif fld_type == FieldType.Hex:<EOL><INDENT>return "<STR_LIT>" + str(fld_len * <NUM_LIT:2>) + "<STR_LIT:)>"<EOL><DEDENT>elif fld_type == FieldType.PowerFactor:<EOL><INDENT>return "<STR_LIT>" + str(fld_len) + "<STR_LIT:)>"<EOL><DEDENT>else:<EOL><INDENT>ekm_log("<STR_LIT>" + str(type) + "<STR_LIT>")<EOL>return "<STR_LIT>"<EOL><DEDENT>

Translate FieldType to portable SQL Type.  Override if needful.
        Args:
            fld_type (int): :class:`~ekmmeters.FieldType` in serial block.
            fld_len (int): Binary length in serial block

        Returns:
            string: Portable SQL type and length where appropriate.


count = <NUM_LIT:0><EOL>for fld in self.m_all_fields:<EOL><INDENT>fld_type = self.m_all_fields[fld][MeterData.TypeValue]<EOL>fld_len = self.m_all_fields[fld][MeterData.SizeValue]<EOL>qry_spec = self.mapTypeToSql(fld_type, fld_len)<EOL>if count > <NUM_LIT:0>:<EOL><INDENT>qry_str += "<STR_LIT>"<EOL><DEDENT>qry_str = qry_str + '<STR_LIT:U+0020>' + fld + '<STR_LIT:U+0020>' + qry_spec<EOL>count += <NUM_LIT:1><EOL><DEDENT>qry_str += ("<STR_LIT>" + Field.Time_Stamp + "<STR_LIT>" +<EOL>"<STR_LIT>" +<EOL>"<STR_LIT>")<EOL>return qry_str<EOL>

Return query portion below CREATE.
        Args:
            qry_str (str): String as built.

        Returns:
            string: Passed string with fields appended.


count = <NUM_LIT:0><EOL>qry_str = "<STR_LIT>"<EOL>qry_str = self.fillCreate(qry_str)<EOL>ekm_log(qry_str, <NUM_LIT:4>)<EOL>return qry_str<EOL>

Reasonably portable SQL CREATE for defined fields.
        Returns:
            string: Portable as possible SQL Create for all-reads table.


@staticmethod<EOL><INDENT>def sqlInsert(def_buf, raw_a, raw_b):<DEDENT>

count = <NUM_LIT:0><EOL>qry_str = "<STR_LIT>"<EOL>for fld in def_buf:<EOL><INDENT>if count > <NUM_LIT:0>:<EOL><INDENT>qry_str += "<STR_LIT>"<EOL><DEDENT>qry_str = qry_str + fld<EOL>count += <NUM_LIT:1><EOL><DEDENT>qry_str += ("<STR_LIT>" + Field.Time_Stamp + "<STR_LIT>" +<EOL>"<STR_LIT>" +<EOL>"<STR_LIT>" +<EOL>"<STR_LIT>")<EOL>count = <NUM_LIT:0><EOL>for fld in def_buf:<EOL><INDENT>if count > <NUM_LIT:0>:<EOL><INDENT>qry_str += "<STR_LIT>"<EOL><DEDENT>fld_type = def_buf[fld][MeterData.TypeValue]<EOL>fld_str_content = def_buf[fld][MeterData.StringValue]<EOL>delim = "<STR_LIT>"<EOL>if (fld_type == FieldType.Hex) or(fld_type == FieldType.String) or(fld_type == FieldType.PowerFactor):<EOL><INDENT>delim = "<STR_LIT:'>"<EOL><DEDENT>qry_str = qry_str + delim + fld_str_content + delim<EOL>count += <NUM_LIT:1><EOL><DEDENT>time_val = int(time.time() * <NUM_LIT:1000>)<EOL>qry_str = (qry_str + "<STR_LIT>" + str(time_val) + "<STR_LIT>" +<EOL>binascii.b2a_hex(raw_a) + "<STR_LIT:'>" + "<STR_LIT>" +<EOL>binascii.b2a_hex(raw_b) + "<STR_LIT>")<EOL>ekm_log(qry_str, <NUM_LIT:4>)<EOL>return qry_str<EOL>

Reasonably portable SQL INSERT for from combined read buffer.
        Args:
            def_buf (SerialBlock): Database only serial block of all fields.
            raw_a (str): Raw A read as hex string.
            raw_b (str): Raw B read (if exists, otherwise empty) as hex string.

        Returns:
            str: SQL insert for passed read buffer


return ("<STR_LIT>" +<EOL>"<STR_LIT>" + Field.Meter_Address + "<STR_LIT>" +<EOL>Field.Time_Stamp + "<STR_LIT>")<EOL>

Reasonably portable Meter_Address and Time_Stamp index SQL create.
        Returns:
            str: SQL CREATE INDEX statement.


return ("<STR_LIT>" +<EOL>"<STR_LIT>" + Field.Meter_Address + "<STR_LIT>")<EOL>

Reasonably portable Meter_Address index SQL create.
        Returns:
            str: SQL CREATE INDEX statement.


qry_str = '<STR_LIT>'<EOL>return qry_str<EOL>

Reasonably portable drop of reads table.
        Returns:
            str: SQL DROP TABLE statement.