def __init__(self, **kwargs):
        """Initializes a model. 
        kwargs:
        `r_mat` must be a square matrix (list of lists of floats).  Diagonal
            elements will be ignored. The columns of this matrix will be 
            multiplied by their corresponding equilibirium frequencies.
        `r_upper` can be used instead of `r_mat.` It should correspond to the
            upper triangle of the R-matrix.
        `equil_freq` must be None a list of the equilibrium frequencies.
        """
        r_upper = kwargs.get('r_upper')
        r_mat = kwargs.get('r_mat')
        sf = kwargs.get('state_freq')
        self.normalize_rates = kwargs.get('normalize_rates', True) # adjust the qmat such that the mean flux is 1.0
        if r_upper:
            if r_mat:
                raise ValueError("r_mat or r_upper cannot both be specified")
            r_mat = _r_upper_to_r_mat(r_upper) 
            _LOG.debug('r_mat from r_upper (%s) is %s' % (str(r_upper), str(r_mat)))
        elif not r_mat:
            raise ValueError("Either r_mat or r_upper must be given")

        priv_mat = []
        param_set = set()
        for row in r_mat:
            priv_row = list(row)
            for n, cell in enumerate(row):
                try:
                    param_set.update(cell.parameters())
                except:
                    priv_row[n] = MutableFloatParameter(cell)
                
            priv_mat.append(tuple(priv_row))
        if sf is None:
            raise ValueError("State frequencies must be specified for a RevDiscStateContTimeModel")
        if isinstance(sf, ProbabilityVectorParameter):
            self._state_freq = sf
        else:
            priv_sf = list(sf)
            for cell in sf:
                try:
                    param_set.update(cell.parameters())
                    priv_sf.append(cell)
                except:
                    priv_sf.append(FloatParameter(cell))
            self._state_freq = ProbabilityVectorParameter(priv_sf)
        param_set.update(set(self._state_freq.parameters()))
        DiscStateContTimeModel.__init__(self, param_list=param_set, **kwargs)
        if r_mat:
            if self.num_states is None:
               self._num_states = len(r_mat)
            self._verify_r_mat(r_mat)
        else:
            raise ValueError("Either r_mat or r_upper must be specified")
        self._r_mat = tuple(priv_mat)
class RevDiscStateContTimeModel(DiscStateContTimeModel):

    def __init__(self, **kwargs):
        """Initializes a model. 
        kwargs:
        `r_mat` must be a square matrix (list of lists of floats).  Diagonal
            elements will be ignored. The columns of this matrix will be 
            multiplied by their corresponding equilibirium frequencies.
        `r_upper` can be used instead of `r_mat.` It should correspond to the
            upper triangle of the R-matrix.
        `equil_freq` must be None a list of the equilibrium frequencies.
        """
        r_upper = kwargs.get('r_upper')
        r_mat = kwargs.get('r_mat')
        sf = kwargs.get('state_freq')
        self.normalize_rates = kwargs.get('normalize_rates', True) # adjust the qmat such that the mean flux is 1.0
        if r_upper:
            if r_mat:
                raise ValueError("r_mat or r_upper cannot both be specified")
            r_mat = _r_upper_to_r_mat(r_upper) 
            _LOG.debug('r_mat from r_upper (%s) is %s' % (str(r_upper), str(r_mat)))
        elif not r_mat:
            raise ValueError("Either r_mat or r_upper must be given")

        priv_mat = []
        param_set = set()
        for row in r_mat:
            priv_row = list(row)
            for n, cell in enumerate(row):
                try:
                    param_set.update(cell.parameters())
                except:
                    priv_row[n] = MutableFloatParameter(cell)
                
            priv_mat.append(tuple(priv_row))
        if sf is None:
            raise ValueError("State frequencies must be specified for a RevDiscStateContTimeModel")
        if isinstance(sf, ProbabilityVectorParameter):
            self._state_freq = sf
        else:
            priv_sf = list(sf)
            for cell in sf:
                try:
                    param_set.update(cell.parameters())
                    priv_sf.append(cell)
                except:
                    priv_sf.append(FloatParameter(cell))
            self._state_freq = ProbabilityVectorParameter(priv_sf)
        param_set.update(set(self._state_freq.parameters()))
        DiscStateContTimeModel.__init__(self, param_list=param_set, **kwargs)
        if r_mat:
            if self.num_states is None:
               self._num_states = len(r_mat)
            self._verify_r_mat(r_mat)
        else:
            raise ValueError("Either r_mat or r_upper must be specified")
        self._r_mat = tuple(priv_mat)



    def get_r_mat(self):
        "Accessor for R-matrix."
        return self._r_mat
    r_mat = property(get_r_mat)
    def get_r_upper(self):
        "Accessor for R-matrix."
        return _r_mat_to_r_upper(self._r_mat)
    r_upper = property(get_r_upper)
    
    def get_state_freq(self):
        "Accessor for state frequencies."
        return self._state_freq
    def set_state_freq(self, v):
        "Accessor for state frequencies."
        _LOG.debug("In RevDiscStateContTimeModel.set_state_freq")
        if isinstance(v, ProbabilityVectorParameter):
            self.substitute_parameter_instance(self._state_freq, v)
            self._state_freq = v
        else:
            self._state_freq.value = v
    state_freq = property(get_state_freq, set_state_freq)
    
    q_mat = property(DiscStateContTimeModel.get_q_mat)

        
    
    def calc_q_mat(self):
        """Uses self._state_freq and self._r_mat to refresh self._q_mat.
        
        As required by the current version of cdsctm_set_q_mat, the Q-matrix
            is rescaled such that each row sums to 0.0 and the weighted 
            average of the diagonal elements is -1.0 (with the weight being the
            associated equilibrium frequency)."""
        assert(self._state_freq is not None)
        _LOG.debug("in self.calc_q_mat: _r_mat = %s _state_freq = %s" % (repr(self._r_mat), str(self._state_freq)))
        ns = self.num_states
        qr = [0.0] * ns
        qm = [list(qr) for i in range(ns)]
        w_mat_sum = 0.0
        for i, rows in enumerate(izip(self._r_mat, self._state_freq)):
            r_row, sf = rows
            q_row = qm[i]
            row_sum = 0.0
            for j, to_state in enumerate(izip(r_row, self._state_freq)):
                r_val, stf = [float(p) for p in to_state]
                if i != j:
                    v = r_val * stf
                    assert(r_val >= 0.0)
                    assert(stf >= 0.0)
                    q_row[j] = v
                    row_sum += v
            q_row[i] = -row_sum
            w_mat_sum += row_sum*self._state_freq[i]
        if self.normalize_rates:
            for q_row in qm:
                for i in xrange(len(q_row)):
                    q_row[i] /= w_mat_sum
        self._q_mat = tuple([tuple(row) for row in qm])
        _LOG.debug("_q_mat = %s" % str(qm))
        return self._q_mat
    
    def _verify_eq_freq_len(self, equil_freq):
        "Raises a ValueError if `equil_freq` is not the correct length"
        nef = len(equil_freq)
        if nef != self._num_states:
            if nef != (1 + self._num_states):
                raise ValueError("The number of states in the r_mat and "\
                             "equil_freq must agree.")

    def _verify_r_mat(self, r_mat):
        """Raises a ValueError if `r_mat` is not the correct shape or has 
        negative values (other than on the diagonal).
        """
        for i, row in enumerate(r_mat):
            if len(row) != self.num_states:
                raise ValueError("The R-matrix must be square.")
            for j, val in enumerate(row):
                if i != j:
                    if val < 0.0:
                        raise ValueError("Off-diagonal elements of the "\
                                         "R-matrix cannot be negative.")
                    if abs(val - float(r_mat[j][i])) > 1.0e-6:
                        raise ValueError("R-matrix must be symmetric")
    def get_num_states(self):
        "Returns the number of states"
        return self._num_states

    def get_adjusted_brlens_list(self, b):
        return [b]

    def get_model_list(self):
        return [self]

    def get_model_probs(self):
        return (1.0,)

    def get_parameters(self):
        return self._parameters

    model_probs = property(get_model_probs)
    r_mat = property(get_r_mat)
    r_upper = property(get_r_upper)
    

    def get_state_freq_value(self):
        return self._state_freq.value
    def set_state_freq_value(self, v):
        self._state_freq.value = v
    state_freq_value = property(get_state_freq_value, set_state_freq_value)