"""
THE MODSOLVER CLASS AND ITS SUBCLASSES
"""
from numpy import matlib as MAT
from numpy import linalg as LIN
from numpy.linalg import matrix_rank
from .. import helpers as HLP
from pymaclab.linalg import qz, ordqz
import numpy as np
import pylab as P
from matplotlib import pyplot as PLT
import copy as COP
from pymaclab.filters._hpfilter import hpfilter
from pymaclab.filters._bkfilter import bkfilter
from isolab import isolab
try:
    import mlabraw
except:
    pass


class MODsolvers(object):
    def __init__(self):
        pass

class PyUhlig(MODsolvers):
    def __init__(self,intup):
        self.ntup = intup[0]
        self.nendo = self.ntup[0]
        self.ncon = self.ntup[1]
        self.nexo = self.ntup[2]

        self.eqindx = intup[1]
        self.vreg = intup[2]
        self.llsys_list = intup[3]
        self.diffli1 = intup[4]
        self.diffli2 = intup[5]
        diffli1 = self.diffli1
        diffli2 = self.diffli2

        deteq = []
        for x in self.eqindx['det']:
            deteq.append(self.llsys_list[x])
        self.deteq = deteq
        expeq = []
        for x in self.eqindx['exp']:
            expeq.append(self.llsys_list[x])
        self.expeq = expeq
        erreq = []
        for x in self.eqindx['err']:
            erreq.append(self.llsys_list[x])
        self.erreq = erreq

        detdif1 = []
        detdif2 = []
        for x in self.eqindx['det']:
            detdif1.append(diffli1[x])
            detdif2.append(diffli2[x])
        expdif1 = []
        expdif2 = []
        for x in self.eqindx['exp']:
            expdif1.append(diffli1[x])
            expdif2.append(diffli2[x])
        errdif1 = []
        errdif2 = []
        for x in self.eqindx['err']:
            errdif1.append(diffli1[x])
            errdif2.append(diffli2[x])
        self.detdif1 = detdif1
        self.detdif2 = detdif2
        self.expdif1 = expdif1
        self.expdif2 = expdif2
        self.errdif1 = errdif1
        self.errdif2 = errdif2

        self.mkmats()

    def mkmats(self):
        deteq = self.deteq
        expeq = self.expeq
        erreq = self.erreq
        nendo = self.nendo
        ncon = self.ncon
        nexo = self.nexo        
        vreg = self.vreg
        detdif1 = self.detdif1
        detdif2 = self.detdif2
        expdif1 = self.expdif1
        expdif2 = self.expdif2
        errdif1 = self.errdif1
        errdif2 = self.errdif2

        # Create argument list for matrix creation
        argli = [['AA',(detdif2,detdif1),deteq,(len(deteq),nendo),(None,'endo','0')],
             ['BB',(detdif2,detdif1),deteq,(len(deteq),nendo),(None,'endo','-1')],
             ['CC',(detdif2,detdif1),deteq,(len(deteq),ncon),(None,'con','0')],
             ['DD',(detdif2,detdif1),deteq,(len(deteq),nexo),(None,'exo','0')],
             ['FF',(expdif2,expdif1),expeq,(len(expeq),nendo),('0','endo','1')],
             ['GG',(expdif2,expdif1),expeq,(len(expeq),nendo),(None,'endo','0')],
             ['HH',(expdif2,expdif1),expeq,(len(expeq),nendo),(None,'endo','-1')],
             ['JJ',(expdif2,expdif1),expeq,(len(expeq),ncon),('0','con','1')],
             ['KK',(expdif2,expdif1),expeq,(len(expeq),ncon),(None,'con','0')],
             ['LL',(expdif2,expdif1),expeq,(len(expeq),nexo),('0','exo','1')],
             ['MM',(expdif2,expdif1),expeq,(len(expeq),nexo),(None,'exo','0')],
             ['NN',(errdif2,errdif1),erreq,(len(erreq),nexo),(None,'exo','0')]]

        # Create all matrices in a loop over argli
        for argx in argli:
            XX = MAT.zeros(argx[3])
            dic1 = dict([[x,'0'] for x in range(argx[3][1])])
            sXX = dict([[x,COP.deepcopy(dic1)] for x in range(len(argx[2]))])
            for y,x in enumerate(argx[2]):
                if vreg(argx[4],x,False,'max'):
                    cont=[[z[0],z[1][1]] for z in vreg(argx[4],x,True,'min')]
                    for z in cont:
                        XX[y,z[1]] = argx[1][0][y][z[0]]
                        sXX[y][z[1]] = argx[1][1][y][z[0]]
            exec('self.'+argx[0]+' = XX')
            exec('self.'+'s'+argx[0]+' = sXX')

    def solve(self,sol_method='do_QZ',Xi_select='all'):
        self.output = {}
        self.Xi_select = Xi_select
        self.sol_method = sol_method
        if self.sol_method == 'do_PP':
            self.do_PP(self.Xi_select)
        elif self.sol_method == 'do_QZ':
            self.do_QZ(self.Xi_select,Tol=1.0000e-06)
        self.do_QRS()

    def do_QZ(self,Xi_select='all',Tol=1.0000e-06):
        # Make uhlig matrices locally available for computations
        AA = self.AA
        BB = self.BB
        CC = self.CC
        DD = self.DD
        FF = self.FF
        GG = self.GG
        HH = self.HH
        JJ = self.JJ
        KK = self.KK
        LL = self.LL
        MM = self.MM
        NN = self.NN
        q_expectational_equ = np.shape(FF)[0]
        m_states = np.shape(FF)[1]
        l_equ = np.shape(CC)[0]
        n_endog = np.shape(CC)[1]
        k_exog = min(np.shape(NN))

#        if HLP.rank(CC) < n_endog:
        if matrix_rank(CC) < n_endog:
            raise uhlerr, 'uhlerror: Rank(CC) needs to be at least\n\
                  equal to the number of endogenous variables'
        if l_equ == 0:
            CC_plus = LIN.pinv(CC)
            CC_0 = (HLP.null(CC.T)).T
            Psi_mat = FF
            Gamma_mat = -GG
            Theta_mat = -HH
            Xi_mat = \
                   np.concatenate((Gamma_mat,Theta_mat,MAT.eye(m_states),\
                          MAT.zeros((m_states,m_states))),1)
            Delta_mat = \
                  np.concatenate((Psi_mat,MAT.zeros((m_states,m_states)),\
                         MAT.zeros((m_states,m_states)),\
                         MAT.zeros((m_states,m_states)),MAT.eye(m_states),1))


        else:
            CC_plus = LIN.pinv(CC)
            CC_0 = HLP.null(CC.T)
            if l_equ > n_endog:
                Psi_mat = \
                    np.concatenate((MAT.zeros((l_equ-n_endog,m_states)),FF-JJ*CC_plus*AA),1)
            elif l_equ == n_endog:
                Psi_mat = np.concatenate((FF-JJ*CC_plus*AA),1)
            Gamma_mat = np.concatenate((CC_0*AA, JJ*CC_plus*BB-GG+KK*CC_plus*AA))
            Theta_mat = np.concatenate((CC_0*BB, KK*CC_plus*BB-HH))
            Xi_mat = \
                   np.concatenate((\
                       np.concatenate((Gamma_mat,Theta_mat),1),\
                       np.concatenate((MAT.identity(m_states),MAT.zeros((m_states,m_states))),1)\
                   ))
            Psi_mat = Psi_mat.reshape(m_states,m_states)
            Delta_mat = \
                  np.concatenate((\
                      np.concatenate((Psi_mat,MAT.zeros((m_states,m_states))),1),\
                      np.concatenate((MAT.zeros((m_states,m_states)),MAT.identity(m_states)),1)\
                  ))

#        (Delta_up,Xi_up,UUU,VVV)=\
#         HLP.qz(Delta_mat,Xi_mat,\
#            mode='complex',\
#            lapackname=lapackname,\
#            lapackpath=lapackpath)
        (Delta_up,Xi_up,UUU,VVV) = qz(Delta_mat,Xi_mat)
        

        d_Delta_up = MAT.diag(Delta_up)
        d_Xi_up = MAT.diag(Xi_up)
        Xi_eigval = MAT.zeros(N.shape(Delta_up))
        for i1 in range(0,N.shape(Delta_up)[0],1):
            Xi_eigval[i1,i1] = d_Xi_up[i1]/d_Delta_up[i1]
        d_Xi_eigval = np.diag(Xi_eigval)
        mat_tmp = MAT.zeros((N.shape(Xi_eigval)[0],3))
        i1=0
        for x in d_Xi_eigval:
            mat_tmp[i1,0] = d_Xi_eigval[i1]
            mat_tmp[i1,1] = abs(d_Xi_eigval)[i1]
            mat_tmp[i1,2] = i1
            i1=i1+1

        Xi_sortval = HLP.sortrows(mat_tmp,1)[:,0]
        # Need to do an argsort() on index column to turn to integers (Booleans) !!
        Xi_sortindex = HLP.sortrows(mat_tmp,1)[:,2].argsort(axis=0)
        Xi_sortabs = HLP.sortrows(mat_tmp,1)[:,1]

        # Root selection branch with Xi_select
        if Xi_select == 'all':
            Xi_select = np.arange(0,m_states,1)

        stake = max(abs(Xi_sortval[Xi_select])) + Tol
        (Delta_up,Xi_up,UUU,VVV) = self.qzdiv(stake,Delta_up,Xi_up,UUU,VVV)
        Lamda_mat = np.diag(Xi_sortval[Xi_select])
        trVVV = VVV.conjugate().T
        VVV_2_1 = trVVV[m_states:2*m_states,0:m_states]
        VVV_2_2 = trVVV[m_states:2*m_states,m_states:2*m_states]
        UUU_2_1 = UUU[m_states:2*m_states,0:m_states]

        PP = -(VVV_2_1.I*VVV_2_2)
        PP = np.real(PP)

        self.PP = PP
        self.CC_plus = CC_plus

    def do_PP(self,Xi_select='all'):
        # Make uhlig matrices locally available for computations
        AA = self.AA
        BB = self.BB
        CC = self.CC
        DD = self.DD
        FF = self.FF
        GG = self.GG
        HH = self.HH
        JJ = self.JJ
        KK = self.KK
        LL = self.LL
        MM = self.MM
        NN = self.NN
        q_expectational_equ = np.shape(FF)[0]
        m_states = np.shape(FF)[1]
        l_equ = np.shape(CC)[0]
        n_endog = np.shape(CC)[1]
        k_exog = min(N.shape(NN))

#        if HLP.rank(CC) < n_endog:
        if matrix_rank(CC) < n_endog:
            raise uhlerr, 'uhlerror: Rank(CC) needs to be at least\n\
                  equal to the number of endogenous variables'
        if l_equ == 0:
            CC_plus = LIN.pinv(CC)
            CC_0 = (HLP.null(CC.T)).T
            Psi_mat = FF
            Gamma_mat = -GG
            Theta_mat = -HH
            Xi_mat = \
                   np.concatenate((Gamma_mat,Theta_mat,MAT.eye(m_states),\
                          MAT.zeros((m_states,m_states))),1)
            Delta_mat = \
                  np.concatenate((Psi_mat,MAT.zeros((m_states,m_states)),\
                         MAT.zeros((m_states,m_states)),\
                         MAT.zeros((m_states,m_states)),MAT.eye(m_states),1))


        else:
            CC_plus = LIN.pinv(CC)
            CC_0 = HLP.null(CC.T)
            if l_equ > n_endog:
                Psi_mat = \
                    np.concatenate((MAT.zeros((l_equ-n_endog,m_states)),FF-JJ*CC_plus*AA),1)
            elif l_equ == n_endog:
                Psi_mat = np.concatenate((FF-JJ*CC_plus*AA),1)
            Gamma_mat = np.concatenate((CC_0*AA, JJ*CC_plus*BB-GG+KK*CC_plus*AA))
            Theta_mat = np.concatenate((CC_0*BB, KK*CC_plus*BB-HH))
            Xi_mat = \
                   np.concatenate((\
                       np.concatenate((Gamma_mat,Theta_mat),1),\
                       np.concatenate((MAT.eye(m_states),MAT.zeros((m_states,m_states))),1)\
                   ))
            Delta_mat = \
                  np.concatenate((\
                      np.concatenate((Psi_mat,MAT.zeros((m_states,m_states))),1),\
                      np.concatenate((MAT.zeros((m_states,m_states)),MAT.eye(m_states)),1)\
                  ))

        (Xi_eigvec,Xi_eigval) = HLP.eig(Xi_mat,Delta_mat)
        tmp_mat = MAT.eye(N.rank(Xi_eigvec))
        for i1 in range(0,N.rank(Xi_eigvec),1):
            tmp_mat[i1,i1] = float(Xi_eigval[0,i1])
        Xi_eigval = tmp_mat


#        if HLP.rank(Xi_eigvec) < m_states:
        if matrix_rank(Xi_eigvec) < m_states:
            raise uhlerr, 'uhlerror: Xi_mat is not diagonalizable!\n\
                  Cannot solve for PP. Maybe you should try the Schur-Decomposition\n\
                  method instead, use do_QZ()!!'


        d_Xi_eigval = np.diag(Xi_eigval)
        mat_tmp = MAT.zeros((N.rank(Xi_eigval),3))
        i1=0
        for x in d_Xi_eigval:
            mat_tmp[i1,0] = d_Xi_eigval[i1]
            mat_tmp[i1,1] = abs(d_Xi_eigval[i1])
            mat_tmp[i1,2] = i1
            i1=i1+1
        Xi_sortval = HLP.sortrows(mat_tmp,1)[:,0]
        # Need to do an argsort() on index column to turn to integers (Booleans) !!
        Xi_sortindex = HLP.sortrows(mat_tmp,1)[:,2].argsort(axis=0)
        Xi_sortabs = HLP.sortrows(mat_tmp,1)[:,1]
        Xi_sortvec = Xi_eigvec[0:2*m_states,:].take(Xi_sortindex.T.A, axis=1)

        # Root selection branch with Xi_select
        if Xi_select == 'all':
            Xi_select = np.arange(0,m_states,1)

        #Create Lambda_mat and Omega_mat
        Lambda_mat = MAT.zeros((len(Xi_select),len(Xi_select)))
        for i1 in range(0,len(Xi_select),1):
            Lambda_mat[i1,i1] = Xi_sortval[Xi_select][i1]
        Omega_mat = Xi_sortvec[m_states:2*m_states,:].take(Xi_select, axis=1)

#        if HLP.rank(Omega_mat) < m_states:
        if matrix_rank(Omega_mat) < m_states:
            raise uhlerr, 'uhlerror: Omega_mat is not invertible!!\n\
                  Therefore, solution for PP is not available'

        PP = Omega_mat*HLP.ctr((HLP.ctr(Omega_mat).I*HLP.ctr(Lambda_mat)))
        self.PP = PP
        self.CC_plus = CC_plus

    def do_QRS(self):
        # Make uhlig matrices locally available for computations
        AA = self.AA
        BB = self.BB
        CC = self.CC
        DD = self.DD
        FF = self.FF
        GG = self.GG
        HH = self.HH
        JJ = self.JJ
        KK = self.KK
        LL = self.LL
        MM = self.MM
        NN = self.NN
        PP = self.PP
        CC_plus = self.CC_plus
        (l_equ,m_states) = MAT.shape(AA)
        (l_equ,n_endog) = MAT.shape(CC)
        (l_equ,k_exog) = MAT.shape(DD)
        if l_equ == 0:
            RR = MAT.zeros((0,m_states))
            VV1 = MAT.kron(MAT.transpose(NN),FF)+MAT.kron(MAT.identity(k_exog),FF*PP+GG)
            VV2 = MAT.kron(MAT.transpose(NN),JJ)+MAT.kron(MAT.identity(k_exog),KK)
            VV = MAT.hstack((VV1,VV2))
        else:
            RR = -CC_plus*(AA*PP+BB)
            VV1 = MAT.kron(MAT.identity(k_exog),AA)
            VV2 = MAT.kron(MAT.identity(k_exog),CC)
            VV3 = MAT.kron(MAT.transpose(NN),FF)+MAT.kron(MAT.identity(k_exog),FF*PP+JJ*RR+GG)
            VV4 = MAT.kron(MAT.transpose(NN),JJ)+MAT.kron(MAT.identity(k_exog),KK)
            VV = MAT.vstack((MAT.hstack((VV1,VV2)),MAT.hstack((VV3,VV4))))
        self.RR = RR

        LLNN_plus_MM = LL*NN+MM
        NON = MAT.hstack((DD.flatten(1),LLNN_plus_MM.flatten(1)))
        try:
            QQSS_vec = -(VV.I*MAT.transpose(NON))
        except MyErr:
            print 'Error: Matrix VV is not invertible!'
        QQ = QQSS_vec[0:m_states*k_exog,:].reshape(-1,m_states).transpose()
        SS = QQSS_vec[(m_states*k_exog):((m_states+n_endog)*k_exog),:].reshape(-1,n_endog).transpose()
        WW1 = MAT.hstack((MAT.identity(m_states),MAT.zeros((m_states,k_exog))))
        WW2 = MAT.hstack((RR*LIN.pinv(PP),SS-RR*LIN.pinv(PP)*QQ))
        WW3 = MAT.hstack((MAT.zeros((k_exog,m_states)),MAT.identity(k_exog)))
        WW = MAT.vstack((WW1,WW2,WW3))
        self.WW = WW
        self.QQ = QQ
        self.SS = SS
        del self.CC_plus

    def qzdiv(self,stake,A,B,Q,Z):
        n = np.shape(A)[0]
        root = np.hstack((abs(N.mat(N.diag(A)).T),abs(N.mat(N.diag(B)).T)))
        index_mat = (root[:,0]<1e-13).choose(root[:,0],1)
        index_mat = (index_mat>1e-13).choose(root[:,0],0)
        root[:,0] = root[:,0]-MAT.multiply(index_mat,(root[:,0]+root[:,1]))
        root[:,1] = root[:,1]/root[:,0]
        for i1 in range(n-1,-1,-1):
            m='none'
            for i2 in range(i1,-1,-1):
                if root[i2,1] > stake or root[i2,1] < -0.1:
                    m=i2
                    break
            if m == 'none':
                return (A,B,Q,Z)
            else:
                for i3 in range(m,i1,1):
                    (A,B,Q,Z) = self.qzswitch(i3,A,B,Q,Z)
                    tmp = COP.deepcopy(root[i3,1])
                    root[i3,1] = root[i3+1,1]
                    root[i3+1,1] = tmp

    def qzswitch(self,i,A,B,Q,Z):
        a = A[i,i]
        d = B[i,i]
        b = A[i,i+1]
        e = B[i,i+1]
        c = A[i+1,i+1]
        f = B[i+1,i+1]
        wz = np.mat(N.hstack(((c*e-f*b),(c*d-f*a).conjugate().T)))
        xy = np.mat(N.hstack(((b*d-e*a).conjugate().T,(c*d-f*a).conjugate().T)))
        n = np.mat(N.sqrt(wz*wz.conjugate().T))
        m = np.mat(N.sqrt(xy*xy.conjugate().T))
        if n.all() == 0:
            return
        else:
            wz = np.mat(wz/n)
            xy = np.mat(xy/m)
            wz = np.vstack((wz,N.hstack((-wz[:,1].T,wz[:,0].T))))
            xy = np.vstack((xy,N.hstack((-xy[:,1].T,xy[:,0].T))))
            A[i:i+2,:] = xy*A[i:i+2,:]
            B[i:i+2,:] = xy*B[i:i+2,:]
            A[:,i:i+2] = A[:,i:i+2]*wz
            B[:,i:i+2] = B[:,i:i+2]*wz
            Z[:,i:i+2] = Z[:,i:i+2]*wz
            Q[i:i+2,:] = xy*Q[i:i+2,:]
        return (A,B,Q,Z)
#----------------------------------------------------------------------------------------------------------------------
class MatUhlig:

    def __init__(self,intup):
        self.ntup = intup[0]
        self.nendo = self.ntup[0]
        self.ncon = self.ntup[1]
        self.nexo = self.ntup[2]

        self.eqindx = intup[1]
        self.vreg = intup[2]
        self.llsys_list = intup[3]
        self.diffli1 = intup[4]
        self.diffli2 = intup[5]
        self.sess1 = intup[6]
        self.vardic = intup[7]
        diffli1 = self.diffli1
        diffli2 = self.diffli2

        deteq = []
        for x in self.eqindx['det']:
            deteq.append(self.llsys_list[x])
        self.deteq = deteq
        expeq = []
        for x in self.eqindx['exp']:
            expeq.append(self.llsys_list[x])
        self.expeq = expeq
        erreq = []
        for x in self.eqindx['err']:
            erreq.append(self.llsys_list[x])
        self.erreq = erreq

        detdif1 = []
        detdif2 = []
        for x in self.eqindx['det']:
            detdif1.append(diffli1[x])
            detdif2.append(diffli2[x])
        expdif1 = []
        expdif2 = []
        for x in self.eqindx['exp']:
            expdif1.append(diffli1[x])
            expdif2.append(diffli2[x])
        errdif1 = []
        errdif2 = []
        for x in self.eqindx['err']:
            errdif1.append(diffli1[x])
            errdif2.append(diffli2[x])
        self.detdif1 = detdif1
        self.detdif2 = detdif2
        self.expdif1 = expdif1
        self.expdif2 = expdif2
        self.errdif1 = errdif1
        self.errdif2 = errdif2

        self.mkmats()

    def mkmats(self):
        deteq = self.deteq
        expeq = self.expeq
        erreq = self.erreq
        nendo = self.nendo
        ncon = self.ncon
        nexo = self.nexo        
        vreg = self.vreg
        detdif1 = self.detdif1
        detdif2 = self.detdif2
        expdif1 = self.expdif1
        expdif2 = self.expdif2
        errdif1 = self.errdif1
        errdif2 = self.errdif2

        # Create argument list for matrix creation
        argli = [['AA',(detdif2,detdif1),deteq,(len(deteq),nendo),(None,'endo','0')],
             ['BB',(detdif2,detdif1),deteq,(len(deteq),nendo),(None,'endo','-1')],
             ['CC',(detdif2,detdif1),deteq,(len(deteq),ncon),(None,'con','0')],
             ['DD',(detdif2,detdif1),deteq,(len(deteq),nexo),(None,'exo','0')],
             ['FF',(expdif2,expdif1),expeq,(len(expeq),nendo),('0','endo','1')],
             ['GG',(expdif2,expdif1),expeq,(len(expeq),nendo),(None,'endo','0')],
             ['HH',(expdif2,expdif1),expeq,(len(expeq),nendo),(None,'endo','-1')],
             ['JJ',(expdif2,expdif1),expeq,(len(expeq),ncon),('0','con','1')],
             ['KK',(expdif2,expdif1),expeq,(len(expeq),ncon),(None,'con','0')],
             ['LL',(expdif2,expdif1),expeq,(len(expeq),nexo),('0','exo','1')],
             ['MM',(expdif2,expdif1),expeq,(len(expeq),nexo),(None,'exo','0')],
             ['NN',(errdif2,errdif1),erreq,(len(erreq),nexo),(None,'exo','0')]]

        # Create all matrices in a loop over argli
        for argx in argli:
            XX = MAT.zeros(argx[3])
            dic1 = dict([[x,'0'] for x in range(argx[3][1])])
            sXX = dict([[x,COP.deepcopy(dic1)] for x in range(len(argx[2]))])
            for y,x in enumerate(argx[2]):
                if vreg(argx[4],x,False,'max'):
                    cont=[[z[0],z[1][1]] for z in vreg(argx[4],x,True,'min')]
                    for z in cont:
                        XX[y,z[1]] = argx[1][0][y][z[0]]
                        sXX[y][z[1]] = argx[1][1][y][z[0]]
            exec('self.'+argx[0]+' = XX')
            exec('self.'+'s'+argx[0]+' = sXX')

    def solve(self,sol_method='do_QZ',Xi_select='all'):
        # Create varnames with correct string length
        tmp_list =[x[1] for x in self.vardic['endo']['var']]\
             +[x[1] for x in self.vardic['con']['var']]\
             +[x[1] for x in self.vardic['exo']['var']]
        tmp_list2 = [[len(x),x] for x in tmp_list]
        tmp_list2.sort()
        max_len = tmp_list2[-1][0]
        i1=0
        for x in tmp_list:
            tmp_list[i1]=x+(max_len-len(x))*' '
            i1=i1+1
        varnstring = 'VARNAMES = ['
        for x in tmp_list:
            varnstring = varnstring + "'" +x[1]+ "'" + ','
        varnstring = varnstring[0:-1]+'];'

        # Start matlab session and calculate
        sess1 = self.sess1
        mlabraw.eval(sess1,'clear all;')
        mlabraw.eval(sess1,varnstring)
        mlabraw.put(sess1,'AA',self.AA)
        mlabraw.put(sess1,'BB',self.BB)
        mlabraw.put(sess1,'CC',self.CC)
        mlabraw.put(sess1,'DD',self.DD)
        mlabraw.put(sess1,'FF',self.FF)
        mlabraw.put(sess1,'GG',self.GG)
        mlabraw.put(sess1,'HH',self.HH)
        mlabraw.put(sess1,'JJ',self.JJ)
        mlabraw.put(sess1,'KK',self.KK)
        mlabraw.put(sess1,'LL',self.LL)
        mlabraw.put(sess1,'MM',self.MM)
        mlabraw.put(sess1,'NN',self.NN)
        mlabraw.eval(sess1,'cd '+mlabpath)
        mlabraw.eval(sess1,'cd Toolkit41')
        message = ' '*70
        eval_list = ['message='+"'"+message+"'",
                 'warnings = [];',
                 'options;',
                 'solve;']
        try:
            for x in eval_list:
                mlabraw.eval(sess1,x)
            self.PP = np.matrix(mlabraw.get(sess1,'PP'))
            self.QQ = np.matrix(mlabraw.get(sess1,'QQ'))
            self.RR = np.matrix(mlabraw.get(sess1,'RR'))
            self.SS = np.matrix(mlabraw.get(sess1,'SS'))
            self.WW = np.matrix(mlabraw.get(sess1,'WW'))
        except MyErr:
            pass
        finally:
            return
#----------------------------------------------------------------------------------------------------------------------
class MatKlein:

    def __init__(self,intup):
        self.sess1 = intup[-1]
        self.uhlig = PyUhlig(intup[:-1])
        self.uhlig.mkmats()
        self.AA = self.uhlig.AA
        self.BB = self.uhlig.BB
        self.CC = self.uhlig.CC
        self.DD = self.uhlig.DD
        self.FF = self.uhlig.FF
        self.GG = self.uhlig.GG
        self.HH = self.uhlig.HH
        self.JJ = self.uhlig.JJ
        self.KK = self.uhlig.KK
        self.LL = self.uhlig.LL
        self.MM = self.uhlig.MM
        self.NN = self.uhlig.NN
        self.mkKleinMats()
        self.outdic = {}

    def mkKleinMats(self):
        # Make uhlig matrices locally available for computations
        AA = self.AA
        BB = self.BB
        CC = self.CC
        DD = self.DD
        FF = self.FF
        GG = self.GG
        HH = self.HH
        JJ = self.JJ
        KK = self.KK
        LL = self.LL
        MM = self.MM
        NN = self.NN

        # Determine size of states, endogenous
        exo_st = MAT.shape(NN)[1]
        endo_st = MAT.shape(BB)[1]
        endo_cn = MAT.shape(CC)[1]
        n_deteq = MAT.shape(AA)[0]
        n_expeq = MAT.shape(JJ)[0]
        tot_st = exo_st+endo_st
        self.tstates = tot_st
        tot_var = tot_st+endo_cn

        klein_A_rtwo = MAT.hstack((LL,GG))
        klein_A_rtwo = MAT.hstack((klein_A_rtwo,JJ))
        klein_A_rtwo_rows = MAT.shape(klein_A_rtwo)[0]
        klein_A_rtwo_cols = MAT.shape(klein_A_rtwo)[1]

        klein_A_rone = MAT.zeros((exo_st,klein_A_rtwo_cols))
        klein_A_rone = MAT.hstack((MAT.identity(exo_st),klein_A_rone[:,exo_st:]))

        klein_A_rthree = MAT.hstack((MAT.zeros((n_deteq,exo_st)),AA))
        klein_A_rthree = MAT.hstack((klein_A_rthree,MAT.zeros((n_deteq,endo_cn))))

        klein_A = MAT.vstack((klein_A_rone,klein_A_rtwo))
        klein_A = MAT.vstack((klein_A,klein_A_rthree))

        klein_B_rone = MAT.zeros((exo_st,klein_A_rtwo_cols))

        klein_B_rone = MAT.hstack((NN,klein_B_rone[:,exo_st:]))
        klein_B_rtwo = MAT.hstack((-MM,-HH))
        klein_B_rtwo = MAT.hstack((klein_B_rtwo,-KK))
        klein_B_rthree = MAT.hstack((-DD,-BB))
        klein_B_rthree = MAT.hstack((klein_B_rthree,-CC))

        klein_B = MAT.vstack((klein_B_rone,klein_B_rtwo))
        klein_B = MAT.vstack((klein_B,klein_B_rthree))  

        self.A = klein_A
        self.B = klein_B

    def solve(self):
        A = self.A
        B = self.B
        tstates = self.tstates
        sess1 = self.sess1
        mlabraw.eval(sess1,'clear all;')
        mlabraw.eval(sess1,'cd '+mlabpath)
        mlabraw.eval(sess1,'cd Klein')
        mlabraw.put(sess1,'AA',A)
        mlabraw.put(sess1,'BB',B)
        mlabraw.put(sess1,'tstates',tstates)
        try:
            mlabraw.eval(sess1,'[F,P,Z11]=solab(AA,BB,tstates)')
            self.F = np.matrix(mlabraw.get(sess1,'F'))
            self.P = np.matrix(mlabraw.get(sess1,'P'))
            self.Z11 = np.matrix(mlabraw.get(sess1,'Z11'))
            self.outdic['P'] = self.P
            self.outdic['F'] = self.F
        except MyErr:
            pass
        finally:
            return
#----------------------------------------------------------------------------------------------------------------------
class MatKleinD:

    def __init__(self,intup):
        self.interm3 = intup[0]
        self.param = intup[1]
        self.sstate_list = intup[2]
        self.varvecs = intup[3]
        self.vardic = intup[4]
        self.vardic2 = intup[5]
        self.shockdic = intup[6]
        self.shockdic2 = intup[7]
        self.varns = intup[8]
        self.re_var = intup[9]
        self.re_var2 = intup[10]
        self.ishockdic = intup[11]
        self.ishockdic2 = intup[12]
        self.sess1 = intup[13]
        self.sstate = intup[14]
        self.mkeqs()
        self.mkvarl()
        self.mkeqs2()
        self.mkgrad()
        self.mkAB()
        self.solab()
        self.mkhess()
        self.solab2()

    def mkeqs(self):
        list_tmp = COP.deepcopy(self.interm3)
        reg2 = RE.compile('\*{2,2}')
        reva2 = self.re_var2
        i1=0
        for x in list_tmp:
            list_tmp[i1]=reg2.sub('^',x.split('=')[0]).strip()
            for y in self.subvars(tuple(self.varvecs['e'])):
                while y in list_tmp[i1]:
                    list_tmp[i1] = list_tmp[i1].replace(y,'1')
            i1=i1+1
        self.interm4 = list_tmp

    def mkvarl(self):
        varlist=[]
        nexost = len(self.varvecs['z'])
        nendost = len(self.varvecs['k'])
        nendocon = len(self.varvecs['y'])
        exost_f = makeForward(self.varvecs['z'],'1','0')
        for x in exost_f:
            varlist.append(x)
        for x in self.varvecs['k']:
            varlist.append(x)
        endocons_f = makeForward(self.varvecs['y'],'1','0')
        for x in endocons_f:
            varlist.append(x)
        exost_l = self.varvecs['z']
        for x in exost_l:
            varlist.append(x)
        endost_l = makeLags(self.varvecs['k'],'1')
        for x in endost_l:
            varlist.append(x)
        for x in self.varvecs['y']:
            varlist.append(x)
        varlist2 = list(self.subvars(tuple(varlist)))
        self.vlist = varlist2

        varlist=[]
        for x in self.varvecs['z']:
            varlist.append(x)
        for x in self.varvecs['k']:
            varlist.append(x)
        endocons_f = makeForward(self.varvecs['y'],'1','0')
        for x in endocons_f:
            varlist.append(x)
        exost_l = makeLags(self.varvecs['z'],'1')
        for x in exost_l:
            varlist.append(x)
        endost_l = makeLags(self.varvecs['k'],'1')
        for x in endost_l:
            varlist.append(x)
        for x in self.varvecs['y']:
            varlist.append(x)
        varlist2 = list(self.subvars(tuple(varlist)))
        self.vlist2 = varlist2

    def mkeqs2(self):
        nexost = len(self.varvecs['z'])
        nendost = len(self.varvecs['k'])
        nendocon = len(self.varvecs['y'])
        list_tmp1 = COP.deepcopy(self.interm4)
        eq_len = len(self.interm4)
        sub_list2 = self.vlist2
        sub_list = self.vlist
        reva2 = self.re_var2
        i1=0
        for x in list_tmp1:
            str_tmp1 = x[:]
            i2=0
            for y1,y2 in zip(sub_list,sub_list2):
                if i1 < eq_len-nexost:
                    while reva2.search(str_tmp1) != None:
                        ma1 = reva2.search(str_tmp1)
                        indx1 = sub_list.index(ma1.group(0))
                        str_tmp1 = str_tmp1.replace(ma1.group(0),'exp(x0('+str(indx1+1)+'))')[:]
                    i2 = i2 + 1
                else:
                    while reva2.search(str_tmp1) != None:
                        ma2 = reva2.search(str_tmp1)
                        indx2 = sub_list2.index(ma2.group(0))
                        str_tmp1 = str_tmp1.replace(ma2.group(0),'exp(x0('+str(indx2+1)+'))')[:]
                    i2 = i2 + 1
            list_tmp1[i1] = str_tmp1
            i1=i1+1

        self.interm5 = list_tmp1        

    def mkfunc(self):
        rege = RE.compile('\*{2,2}')
        inde = ' '*2
        eq_len=len(self.interm5)
        mfile=open(path_opts['MlabPath']['path']+'/Klein/'+'mfunc.m','w')
        mfile.write('function y = mfunc(x0)\n')
        mfile.write(inde+'%Parameter Values\n')
        for x in self.param.items():
            mfile.write(inde+x[0]+'='+str(x[1])+';\n')
        mfile.write('\n')
        mfile.write(inde+'%Steady State Values\n')
        for x in self.sstate_list:
            x[0]=rege.sub('^',x[0])
            x[1]=rege.sub('^',x[1])
            mfile.write(inde+x[0]+'='+str(x[1])+';\n')
        mfile.write('\n')
        mfile.write(inde+'y=zeros('+str(eq_len)+',1);\n')
        mfile.write('\n')
        for i1,i2 in zip(range(1,eq_len+1,1),self.interm5):
            mfile.write(inde+'y('+str(i1)+')='+i2+';'+'\n')
        mfile.close()

    def mkgrad(self):
        self.mkfunc()
        sess1 = self.sess1
        sstate = self.sstate
        ssdic = sstate[0]
        ssdic.update(sstate[1])
        ssdic2 = {}
        for x in ssdic.keys():
            if x[-4:] == '_bar':
                ssdic2[x] = ssdic[x]
        for x in ssdic2.keys():
            ssdic2[x] = np.log(ssdic2[x])
        vlist2 = []
        for x in self.vlist:
            ma = self.re_var2.search(x)
            tvar = ma.group('var')
            tvar = tvar.upper()
            tvar = tvar+'_bar'
            vlist2.append(tvar)
        invec = []
        for x in vlist2:
            invec.append(ssdic2[x])
        mlabraw.eval(sess1,'clear all;')
        mlabraw.eval(sess1,'cd '+path_opts['MlabPath']['path'])
        mlabraw.eval(sess1,'cd Klein')
        mlabraw.put(sess1,'x0',invec)
        mlabraw.eval(sess1,"grdm=centgrad('mfunc',x0)")
        gradm = np.matrix(mlabraw.get(sess1,'grdm'))
        self.gradm = gradm

    def mkAB(self):
        nexost = len(self.varvecs['z'])
        nendost = len(self.varvecs['k'])
        nendocon = len(self.varvecs['y'])
        A = self.gradm[:,:nexost+nendost+nendocon]
        B = -self.gradm[:,nexost+nendost+nendocon:]
        self.AA = A
        self.BB = B

    def solab(self):
        A = self.AA
        B = self.BB
        tstates = len(self.varvecs['k'])+len(self.varvecs['z'])
        (F,P,retcon) = isolab(A,B,tstates,MAT.shape(A)[0])
        if MAT.sum(P.reshape(-1,1)) == 0.0:
            return
        else:
            self.P = np.matrix(P)
            self.F = np.matrix(F)

    def mkhess(self):
        self.mkfunc()
        sess1 = self.sess1
        sstate = self.sstate
        ssdic = sstate[0]
        ssdic.update(sstate[1])
        ssdic2 = {}
        for x in ssdic.keys():
            if x[-4:] == '_bar':
                ssdic2[x] = ssdic[x]
        for x in ssdic2.keys():
            ssdic2[x] = np.log(ssdic2[x])
        vlist2 = []
        for x in self.vlist:
            ma = self.re_var2.search(x)
            tvar = ma.group('var')
            tvar = tvar.upper()
            tvar = tvar+'_bar'
            vlist2.append(tvar)
        invec = []
        for x in vlist2:
            invec.append(ssdic2[x])
        mlabraw.eval(sess1,'clear all;')
        mlabraw.eval(sess1,'cd '+path_opts['MlabPath']['path'])
        mlabraw.eval(sess1,'cd Klein')
        mlabraw.put(sess1,'x0',invec)
        mlabraw.eval(sess1,"hessm=centhess('mfunc',x0)")
        hessm = np.matrix(mlabraw.get(sess1,'hessm'))
        self.hessm = hessm

    def solab2(self):
        sess1 = self.sess1
        mlabraw.eval(sess1,'clear all;')
        mlabraw.eval(sess1,'cd '+path_opts['MlabPath']['path'])
        mlabraw.eval(sess1,'cd Klein')
        mlabraw.put(sess1,'gradm',self.gradm)
        mlabraw.put(sess1,'hessm',self.hessm)
#----------------------------------------------------------------------------------------------------------------------
class MatWood:

    def __init__(self,intup):
        self.jAA = intup[0]
        self.jBB = intup[1]
        self.nexo = intup[2]
        self.ncon = intup[3]
        self.nendo = intup[4]
        self.sess1 = intup[5]
        self.NY = self.ncon+self.nendo
        self.NK = self.nendo
        self.NX = self.nexo
        self.mkwoodm()

    def solve(self):
        self.reds()
        self.solds()

    def mkwoodm(self):
        AA = self.jAA
        BB = self.jBB
        nendo = self.nendo
        nexo = self.nexo
        ncon = self.ncon
        nstates = nexo+nendo

        wAA = MAT.hstack((AA[:-nexo,nstates:],AA[:-nexo,nexo:nstates]))
        #wAA = MAT.hstack((AA[:,nstates:],AA[:,:nstates]))
        wBB = MAT.hstack((BB[:-nexo,nstates:],BB[:-nexo,nexo:nstates]))
        #wBB = MAT.hstack((BB[:,nstates:],BB[:,:nstates]))
        wCC = BB[:-nexo,:nexo]
        #wCC = MAT.zeros((ncon+nstates,1))


        self.wAA = wAA
        self.wBB = wBB
        self.wCC = wCC

    def reds(self):
        A = self.wAA
        B = self.wBB
        C = self.wCC
        NX = self.NX
        NK = self.NK
        NY = self.NY
        sess1 = self.sess1
        mlabraw.eval(sess1,'clear all;')
        mlabraw.eval(sess1,'cd '+mlabpath)
        mlabraw.eval(sess1,'cd Woodford')
        mlabraw.put(sess1,'wAA',A)
        mlabraw.put(sess1,'wBB',B)
        mlabraw.put(sess1,'wCC',C)
        mlabraw.put(sess1,'NX',NX)
        mlabraw.put(sess1,'NY',NY)
        mlabraw.put(sess1,'NK',NK)
        mlabraw.eval(sess1,'[Br,Cr,Lr,NF] = redsf(wAA,wBB,wCC,NY,NX,NK)')
        self.Br = np.matrix(mlabraw.get(sess1,'Br'))
        self.Cr = np.matrix(mlabraw.get(sess1,'Cr'))
        self.Lr = np.matrix(mlabraw.get(sess1,'Lr'))
        self.NF = np.matrix(mlabraw.get(sess1,'NF'))

    def solds(self):
        Br = self.Br
        Cr = self.Cr
        Lr = self.Lr
        NF = self.NF
        NX = self.NX
        NK = self.NK
        NY = self.NY
        sess1 = self.sess1
        mlabraw.eval(sess1,'clear all;')
        mlabraw.eval(sess1,'cd '+mlabpath)
        mlabraw.eval(sess1,'cd Woodford')
        mlabraw.put(sess1,'Br',Br)
        mlabraw.put(sess1,'Cr',Cr)
        mlabraw.put(sess1,'Lr',Lr)
        mlabraw.put(sess1,'NF',NF)
        mlabraw.put(sess1,'NX',NX)
        mlabraw.put(sess1,'NY',NY)
        mlabraw.put(sess1,'NK',NK)
        mlabraw.eval(sess1,'[D,F,G,H] = soldsf(Br,Cr,Lr,NY,NX,NK,NF)')
        self.D = np.matrix(mlabraw.get(sess1,'D'))
        self.F = np.matrix(mlabraw.get(sess1,'F'))
        self.G = np.matrix(mlabraw.get(sess1,'G'))
        self.H = np.matrix(mlabraw.get(sess1,'H'))
#----------------------------------------------------------------------------------------------------------------------
class ForKlein:

    def __init__(self,intup):
        self.uhlig = PyUhlig(intup)
        self.uhlig.mkmats()
        self.AA = self.uhlig.AA
        self.BB = self.uhlig.BB
        self.CC = self.uhlig.CC
        self.DD = self.uhlig.DD
        self.FF = self.uhlig.FF
        self.GG = self.uhlig.GG
        self.HH = self.uhlig.HH
        self.JJ = self.uhlig.JJ
        self.KK = self.uhlig.KK
        self.LL = self.uhlig.LL
        self.MM = self.uhlig.MM
        self.NN = self.uhlig.NN
        self.mkKleinMats()
        self.outdic = {}

    def mkKleinMats(self):
        # Make uhlig matrices locally available for computations
        AA = self.AA
        BB = self.BB
        CC = self.CC
        DD = self.DD
        FF = self.FF
        GG = self.GG
        HH = self.HH
        JJ = self.JJ
        KK = self.KK
        LL = self.LL
        MM = self.MM
        NN = self.NN

        # Determine size of states, endogenous
        exo_st = MAT.shape(NN)[1]
        endo_st = MAT.shape(BB)[1]
        endo_cn = MAT.shape(CC)[1]
        n_deteq = MAT.shape(AA)[0]
        n_expeq = MAT.shape(JJ)[0]
        tot_st = exo_st+endo_st
        self.tstates = tot_st
        tot_var = tot_st+endo_cn

        klein_A_rtwo = MAT.hstack((LL,GG))
        klein_A_rtwo = MAT.hstack((klein_A_rtwo,JJ))
        klein_A_rtwo_rows = MAT.shape(klein_A_rtwo)[0]
        klein_A_rtwo_cols = MAT.shape(klein_A_rtwo)[1]

        klein_A_rone = MAT.zeros((exo_st,klein_A_rtwo_cols))
        klein_A_rone = MAT.hstack((MAT.identity(exo_st),klein_A_rone[:,exo_st:]))

        klein_A_rthree = MAT.hstack((MAT.zeros((n_deteq,exo_st)),AA))
        klein_A_rthree = MAT.hstack((klein_A_rthree,MAT.zeros((n_deteq,endo_cn))))

        klein_A = MAT.vstack((klein_A_rone,klein_A_rtwo))
        klein_A = MAT.vstack((klein_A,klein_A_rthree))

        klein_B_rone = MAT.zeros((exo_st,klein_A_rtwo_cols))

        klein_B_rone = MAT.hstack((NN,klein_B_rone[:,exo_st:]))
        klein_B_rtwo = MAT.hstack((-MM,-HH))
        klein_B_rtwo = MAT.hstack((klein_B_rtwo,-KK))
        klein_B_rthree = MAT.hstack((-DD,-BB))
        klein_B_rthree = MAT.hstack((klein_B_rthree,-CC))

        klein_B = MAT.vstack((klein_B_rone,klein_B_rtwo))
        klein_B = MAT.vstack((klein_B,klein_B_rthree))  

        self.A = klein_A
        self.B = klein_B

    def solve(self):
        A = self.A
        B = self.B
        tstates = MAT.shape(self.AA)[1] + MAT.shape(self.DD)[1]
        (F,P,retcon) = isolab(A,B,tstates,MAT.shape(A)[0])
        if MAT.sum(P.reshape(-1,1)) == 0.0:
            return
        else:
            self.P = np.matrix(P)
            self.F = np.matrix(F)
#----------------------------------------------------------------------------------------------------------------------
class PyKlein2D:

    def __init__(self,intup):
        self.gra = intup[0]
        self.hes = intup[1]
        self.nendo = intup[2]
        self.nexo = intup[3]
        self.ncon = intup[4]
        self.sigma = intup[5]
        self.A = intup[6]
        self.B = intup[7]
        self.vardic = intup[8]
        self.vdic = intup[9]
        self.modname = intup[10]
        self.audic = intup[11]
        self.nacon = len(self.audic['con']['var'])
        self.naendo = len(self.audic['endo']['var'])
        if self.vardic['other']['var']:
            self.numjl = intup[12]
            self.numhl = intup[13]
            self.nother = intup[14]
            self.oswitch = 1
            kintup = (self.gra,self.nendo,
                  self.nexo,self.ncon,
                  self.sigma,self.A,self.B,
                  self.vardic,self.vdic,
                  self.modname,self.audic,
                  self.numjl,self.nother)
        else:
            self.oswitch = 0
            kintup = (self.gra,self.nendo,
                  self.nexo,self.ncon,
                  self.sigma,self.A,self.B,
                  self.vardic,self.vdic,
                  self.modname,self.audic)
        self.tstates = self.nendo+self.nexo
        self.forkleind = ForKleinD(kintup)
        self.ssigma = self.mkssigma(self.tstates,self.nexo,self.sigma)

    def mkssigma(self,tstates,nexo,sigma):
        ssigma = MAT.zeros((tstates,tstates))
        for i in range(nexo):
            ssigma[i,i] = sigma[i,i]
        return ssigma

    def solab2(self):

        # Tracem function
        def tracem(xmat):
            n = MAT.shape(xmat)[1]
            m = MAT.shape(xmat)[0]/n
            ymat = MAT.zeros((m,1))
            for i1 in xrange(int(m)):
                ymat[i1,0]=MAT.trace(xmat[n*i1:i1*n+1,:n])
            return ymat

        ssigma = self.ssigma
        pp = self.P
        ff = self.F
        gra = self.gra
        hes = self.hes
        m = self.ncon+self.nendo+self.nexo
        ny = self.ncon
        nx = self.tstates

        f1 = gra[:,:nx]
        f2 = gra[:,nx:m]
        f4 = gra[:,m+nx:2*m]

        mm = MAT.vstack((pp,ff*pp,MAT.eye(nx),ff))
        aa1 = MAT.kron(MAT.eye(m),mm.T)*hes*mm
        bb1 = MAT.kron(f1,MAT.eye(nx))
        bb2 = MAT.kron(f2,MAT.eye(nx))
        bb4 = MAT.kron(f4,MAT.eye(nx))
        cc1 = MAT.kron(MAT.eye(ny),pp.T)
        cc2 = MAT.kron(ff,MAT.eye(nx))

        aa_1 = MAT.kron(MAT.eye(nx),bb4)+MAT.kron(pp.T,bb2*cc1)
        aa_2 = MAT.kron(MAT.eye(nx),bb1+bb2*cc2)
        aa = MAT.hstack((aa_1,aa_2))
        sol = np.linalg.solve(-aa,HLP.ctr(aa1.flatten(1)))
        ee = HLP.ctr(sol[:nx**2*ny].reshape(-1,nx*ny))
        gg = HLP.ctr(sol[nx**2*ny:].reshape(-1,nx**2))
        ma = 2.0*MAT.hstack((f1+f2*ff,f2+f4))
        eyeff = MAT.vstack((MAT.eye(nx),ff,MAT.zeros((m,nx))))
        ve_1 = f2*tracem(MAT.kron(MAT.eye(ny),ssigma)*ee)
        ve_2 = tracem(MAT.kron(MAT.eye(m),HLP.ctr(eyeff))*hes*eyeff*ssigma)
        ve = ve_1 + ve_2
        kxy = -(ma.I)*ve
        kx = kxy[:nx]
        ky = kxy[nx:]
        self.E = ee
        self.G = gg
        self.KX = kx
        self.KY = ky

    def solve(self):
        self.forkleind.solve()
        self.P = self.forkleind.P
        self.F = self.forkleind.F
        self.solab2()

    def sim(self,tlen,sntup=None):
        # Add 1000 observations, as they will be thrown away
        # Add one more observation to start first-order vector
        exoli = [x[1] for x in self.vardic['exo']['var']]
        indx=[]
        if sntup == None:
            indx = range(len(exoli))
        else:
            for name in sntup:
                if name not in exoli:
                    return 'Error: '+name+' is not a valid exo variable for this model!'
                else:
                    indx.append(exoli.index(name))
        indx.sort()
        ncon = self.ncon
        nexo = self.nexo
        nendo = self.nendo
        tstates = self.tstates
        tlena = 1000+tlen
        sigma = self.sigma
        ssigma = self.ssigma
        if self.oswitch:
            numjl = self.numjl
            numhl = self.numhl
        kx = self.KX
        ky = self.KY
        pp = self.P
        ff = self.F
        ee = self.E
        gg = self.G
        count = 0
        for varia in MAT.diag(sigma):
            if locals().has_key('ranvec'):
                if count in indx:
                    ranvec = MAT.vstack((ranvec,N.sqrt(varia)*MAT.matrix(N.random.standard_normal(tlena))))
                else:
                    ranvec = MAT.vstack((ranvec,MAT.zeros((1,tlena))))
            else:
                if count in indx:
                    ranvec = np.sqrt(varia)*MAT.matrix(N.random.standard_normal(tlena))
                else:
                    ranvec = MAT.zeros((1,tlena))
            count = count + 1

        ranvec = MAT.vstack((ranvec,MAT.zeros((nendo,tlena))))

        x_one_m1 = ranvec[:,0]
        x_one_0 = pp*x_one_m1
        x_two_m1 = kx + ranvec[:,0]
        y_one_0 = ff*x_one_m1
        y_one_m1 = MAT.zeros(y_one_0.shape)
        y_two_0 = ky+0.5*MAT.kron(MAT.eye(ncon),x_one_m1.T)*ee*x_one_m1
        if self.oswitch:
            nother = self.nother
            o_one_0 = numjl*MAT.vstack((x_one_0,y_one_0,x_one_m1,y_one_m1))
            o_two_0 = numjl*MAT.vstack((x_one_0,y_one_0,x_one_m1,y_one_m1))+\
                0.5*MAT.kron(MAT.eye(nother),MAT.vstack((x_one_0,y_one_0,x_one_m1,y_one_m1)).T)*\
                numhl*MAT.vstack((x_one_0,y_one_0,x_one_m1,y_one_m1))

        x_one_c = COP.deepcopy(x_one_m1)
        y_one_c = COP.deepcopy(y_one_0)
        x_two_c = COP.deepcopy(x_two_m1)
        y_two_c = COP.deepcopy(y_two_0)
        if self.oswitch:
            o_one_c = COP.deepcopy(o_one_0)
            o_two_c = COP.deepcopy(o_two_0)

        x_one = COP.deepcopy(x_one_c)
        y_one = COP.deepcopy(y_one_c)
        x_two = COP.deepcopy(x_two_c)
        y_two = COP.deepcopy(y_two_c)
        if self.oswitch:
            o_one = COP.deepcopy(o_one_c)
            o_two = COP.deepcopy(o_two_c)

        for i1 in range(1,ranvec.shape[1],1):

            x_one_n = pp*x_one_c+ranvec[:,i1]
            y_one_n = ff*x_one_c

            x_two_n = kx+pp*x_two_c+\
                0.5*MAT.kron(MAT.eye(tstates),x_one_c.T)*\
                gg*x_one_c+ranvec[:,i1]

            y_two_n = ky+ff*x_two_c+\
                0.5*MAT.kron(MAT.eye(ncon),x_one_c.T)*\
                ee*x_one_c

            if self.oswitch:
                o_one_n = numjl*MAT.vstack((x_one_n,y_one_n,x_one_c,y_one_c))
                o_two_n = numjl*MAT.vstack((x_one_n,y_one_n,x_one_c,y_one_c))+\
                    0.5*MAT.kron(MAT.eye(nother),MAT.vstack((x_one_n,y_one_n,x_one_c,y_one_c)).T)*\
                    numhl*MAT.vstack((x_one_n,y_one_n,x_one_c,y_one_c))

            x_one = MAT.hstack((x_one,x_one_c))
            y_one = MAT.hstack((y_one,y_one_n))
            x_two = MAT.hstack((x_two,x_two_c))
            y_two = MAT.hstack((y_two,y_two_n))
            if self.oswitch:
                o_one = MAT.hstack((o_one,o_one_n))
                o_two = MAT.hstack((o_two,o_two_n))

            x_one_c = x_one_n
            y_one_c = y_one_n
            x_two_c = x_one_n
            y_two_c = y_two_n
            if self.oswitch:
                o_one_c = o_one_n
                o_two_c = o_two_n

        # Throw away first 1000 obs
        x_one = x_one[:,1000:]
        y_one = y_one[:,1000:]
        y_two = y_two[:,1000:]
        x_two = x_two[:,1000:]
        if self.oswitch:
            o_one = o_one[:,1000:]
            o_two = o_two[:,1000:]

        self.sim_y_two = y_two
        self.sim_y_one = y_one
        self.sim_x_two = x_two
        self.sim_x_one = x_one
        self.insim = [self.sim_x_two,self.sim_y_two]
        if self.oswitch:
            self.sim_o_one = o_one
            self.sim_o_two = o_two
            self.insim = self.insim + [self.sim_o_two,]

    def mkcvar(self,vname=False,insim='insim'):
        # Now also produce unconditional variances, and normal. variances with v
        # Check if simul data is available
        if insim not in dir(self):
            return "Error: Can't produce uncond. variance table without simulation data!"

        exoli = [x[1] for x in self.vardic['exo']['var']]
        endoli = [x[1] for x in self.vardic['endo']['var']]
        stateli = exoli + endoli
        conli = [x[1] for x in self.vardic['con']['var']]
        alli = stateli+conli
        if self.oswitch:
            otherli = [x[1] for x in self.vardic['other']['var']]
            alli = alli + otherli

        # Check if vname is valid
        if vname not in alli:
            return 'Error: '+vname+' is not a valid variable for this model!'
        insim = eval('self.'+insim)
        osim_x = COP.deepcopy(insim[0])
        osim_y = COP.deepcopy(insim[1])
        nendo = self.nendo
        nexo = self.nexo
        ncon = self.ncon

        # Now hp filter the simulations before graphing according to filtup
        for i1 in xrange(osim_y.shape[0]):
            yy = osim_y[i1,:].__array__().T
            woy = np.zeros((osim_y.shape[1],3))
            lam = 1600
            yyf = MAT.matrix(hpfilter(yy,woy,osim_y.shape[1],1600,0))
            osim_y[i1,:] = yyf[0]
        # Now filter the state variables!
        for i1 in xrange(osim_x.shape[0]):
            xx = osim_x[i1,:].__array__().T
            wox = np.zeros((osim_x.shape[1],3))
            lam = 1600
            xxf = MAT.matrix(hpfilter(xx,wox,osim_x.shape[1],1600,0))
            osim_x[i1,:] = xxf[0]

        if self.oswitch:
            osim_o = COP.deepcopy(insim[2])
            # Now hp filter the other variables!
            for i1 in xrange(osim_o.shape[0]):
                oo = osim_o[i1,:].__array__().T
                woo = np.zeros((osim_o.shape[1],3))
                lam = 1600
                oof = MAT.matrix(hpfilter(oo,woo,osim_o.shape[1],1600,0))
                osim_o[i1,:] = oof[0]

        # Stack all matrices into one
        allmat = MAT.vstack((osim_x,osim_y))
        if self.oswitch:
            allmat = MAT.vstack((allmat,osim_o))
        varmat = MAT.zeros((allmat.shape[0],1))
        for i1 in range(allmat.shape[0]):
            varmat[i1,0] = np.var(allmat[i1,:].A.flatten(1))

        if vname:
            relmat = MAT.zeros((allmat.shape[0],1))
            indx = alli.index(vname)
            varvari = np.var(allmat[indx,:].A.flatten(1))
            for i1 in range(allmat.shape[0]):
                relmat[i1,0] = varmat[i1,0]/varvari
            self.cvarm = MAT.hstack((varmat,relmat))
        else:
            self.cvarm = varmat



    def mkact(self,vname,intup=None,insim='insim'):
        # Now also produce autocorrelation table
        # Check if simul data is available
        if insim not in dir(self):
            return "Error: Can't produce autocorrelation table without simulation data!"

        exoli = [x[1] for x in self.vardic['exo']['var']]
        endoli = [x[1] for x in self.vardic['endo']['var']]
        stateli = exoli + endoli
        conli = [x[1] for x in self.vardic['con']['var']]
        alli = stateli+conli
        if self.oswitch:
            otherli = [x[1] for x in self.vardic['other']['var']]
            alli = alli + otherli
        # Check if vname is valid
        if vname not in alli:
            return 'Error: '+vname+' is not a valid variable for this model!'

        if intup == None:
            lags = 3
            leads = 3
        else:
            lags = intup[0]
            leads = intup[1]

        insim = eval('self.'+insim)
        osim_x = COP.deepcopy(insim[0])
        osim_y = COP.deepcopy(insim[1])

        # Now hp filter the simulations before graphing according to filtup
        for i1 in xrange(osim_y.shape[0]):
            yy = osim_y[i1,:].__array__().T
            woy = np.zeros((osim_y.shape[1],3))
            lam = 1600
            yyf = MAT.matrix(hpfilter(yy,woy,osim_y.shape[1],1600,0))
            osim_y[i1,:] = yyf[0]
        # Now filter the state variables!
        for i1 in xrange(osim_x.shape[0]):
            xx = osim_x[i1,:].__array__().T
            wox = np.zeros((osim_x.shape[1],3))
            lam = 1600
            xxf = MAT.matrix(hpfilter(xx,wox,osim_x.shape[1],1600,0))
            osim_x[i1,:] = xxf[0]

        sim_x = osim_x[:,lags:-leads]
        sim_xf = osim_x[:,leads+1:]
        sim_yf = osim_y[:,leads+1:]
        sim_y = osim_y[:,lags:-leads]
        sim_xl = osim_x[:,:-lags-1]
        sim_yl = osim_y[:,:-lags-1]

        if self.oswitch:
            osim_o = COP.deepcopy(insim[2])
            # Now hp filter the other variables!
            for i1 in xrange(osim_o.shape[0]):
                oo = osim_o[i1,:].__array__().T
                woo = np.zeros((osim_o.shape[1],3))
                lam = 1600
                oof = MAT.matrix(hpfilter(oo,woo,osim_o.shape[1],1600,0))
                osim_o[i1,:] = oof[0]
            sim_o = osim_o[:,lags:-leads]
            sim_of = osim_o[:,leads+1:]
            sim_ol = osim_o[:,:-lags-1]
            alli = alli + otherli

        posa = alli.index(vname)
        actm = MAT.zeros((len(alli),lags+1+leads))
        sima = MAT.vstack((sim_x,sim_y))
        sima_f = MAT.vstack((sim_xf,sim_yf))
        sima_l = MAT.vstack((sim_xl,sim_yl))
        if self.oswitch:
            sima = MAT.vstack((sima,sim_o))
            sima_f = MAT.vstack((sima_f,sim_of))
            sima_l = MAT.vstack((sima_l,sim_ol))
        for i1 in range(sima.shape[0]):
            # Do lags
            for i2 in range(lags):
                actm[i1,lags-i2-1] = np.round(STA.corrcoef(sima[posa,:].A.flatten(1),sima_l[i1,i2:sima_l.shape[1]-lags+i2+1].A.flatten(1))[1,0],3)
            # Do current
            actm[i1,lags] = np.round(STA.corrcoef(sima[posa,:].A.flatten(1),sima[i1,:].A.flatten(1))[1,0],3)
            # Do leads
            for i2 in range(leads):
                actm[i1,lags+1+i2] = np.round(STA.corrcoef(sima[posa,:].A.flatten(1),sima_f[i1,i2:sima_f.shape[1]-leads+i2+1].A.flatten(1))[1,0],3)

        self.actm = actm
        self.actname = vname
        if intup:
            self.actin = intup

    def show_act(self):
        if 'actname' not in dir(self):
            return 'Error: You have not produced any autocorrelation table yet!'
        nexo = self.nexo
        nendo = self.nendo
        ncon = self.ncon
        naendo = self.naendo
        nacon = self.nacon
        nother = len(self.vardic['other']['var'])
        respva = COP.deepcopy(self.actname)
        if 'actin' in dir(self):
            lags = COP.deepcopy(int(self.actin[0]))
            leads = COP.deepcopy(int(self.actin[1]))
        else:
            lags = 3
            leads = 3
        actm = COP.deepcopy(self.actm)
        vdic = self.vdic
        allvari = [x[1] for x in vdic['exo']]
        allvari = allvari + [x[1] for x in vdic['endo']]
        allvari = allvari + [x[1] for x in vdic['con']]
        if self.oswitch:
            allvari = allvari + [x[1] for x in vdic['other']]
        allvari = allvari[:nexo+nendo-naendo]+allvari[nexo+nendo:nexo+nendo+ncon-nacon]
        actm = MAT.vstack((actm[:nexo+nendo-naendo,:],actm[nexo+nendo:nexo+nendo+ncon-nacon,:]))

        # determine longest varname
        vnmax = 0
        for vari in allvari:
            if len(vari) > vnmax:
                vnmax = len(vari)
        print ''
        print 'Autocorrelation table, current '+respva
        print '='*65
        for i1,vari in enumerate(allvari):
            print vari+(vnmax-len(vari))*' '+'  |'+str(actm[i1,:])[2:-2]

    def show_sim(self,intup,filtup=None,insim='insim'):
        # Check if simulations have been carried out
        if insim not in dir(self):
            return 'Error: You have not produced any simulations yet! Nothing to graph!'
        mname = self.modname
        vardic = self.vardic
        insim = eval('self.'+insim)
        sim_x = COP.deepcopy(insim[0])
        sim_y = COP.deepcopy(insim[1])
        tlen = sim_x.shape[1]
        if self.oswitch:
            sim_o = COP.deepcopy(insim[2])
            nother = self.nother
            otherli = [x[1] for x in vardic['other']['var']]
        nexo = self.nexo
        nendo = self.nendo
        ncon = self.ncon
        conli = [x[1] for x in vardic['con']['var']]
        endoli = [x[1] for x in vardic['endo']['var']]
        exoli = [x[1] for x in vardic['exo']['var']]

        # If filtup is None, create filtup from vardic
        if filtup == None:
            filli = [0]*len(intup)
            for i1,x in enumerate(intup):
                for y in vardic.keys():
                    if x in [z[1] for z in vardic[y]['var']]:
                        indx = [z[1] for z in vardic[y]['var']].index(x)
                        if 'hp' in [z for z in vardic[y]['mod']][indx]:
                            filli[i1] = 1
                        elif 'bk' in [z for z in vardic[y]['mod']][indx]:
                            filli[i1] = 2
            filtup = tuple(filli)


        stateli = exoli+endoli
        alli = stateli+conli
        if self.oswitch:
            alli = alli+otherli
        # Check if all name in intup are available to graph
        for name in intup:
            if name not in alli:
                return 'Error: '+name+' is not a valid variable name for this model!'
        # Create x, y and z indeces
        indx = []
        indy = []
        indo = []
        for name in intup:
            if name in stateli:
                indx.append(stateli.index(name))
            elif name in conli:
                indy.append(conli.index(name))
            elif self.oswitch and name in otherli:
                indo.append(otherli.index(name))
        leg = []
        indx.sort()
        indy.sort()
        indo.sort()     

        # Now hp filter the simulations before graphing according to filtup
        for i1 in xrange(sim_y.shape[0]):
            if indy and (i1 in indy) and filtup[list(intup).index(conli[i1])]:
                if filtup[list(intup).index(conli[i1])] == 1:
                    conli[i1] = conli[i1]+'(hpf)'
                    yy = sim_y[i1,:].__array__().T
                    woy = np.zeros((tlen,3))
                    lam = 1600
                    yyf = MAT.matrix(hpfilter(yy,woy,tlen,1600,0))
                    sim_y[i1,:] = yyf[0]*100
                elif filtup[list(intup).index(conli[i1])] == 2:
                    conli[i1] = conli[i1]+'(bkf)'
                    yy = sim_y[i1,:].__array__().T
                    woy = np.zeros((tlen,1))
                    up = 6
                    dn = 32
                    kkl = 12
                    yyf = MAT.matrix(bkfilter(yy,up,dn,kkl,tlen))
                    sim_y[i1,:] = yyf[0]*100
        # Now filter the state variables!
        for i1 in xrange(sim_x.shape[0]):
            if indx and (i1 in indx) and filtup[list(intup).index(stateli[i1])]:
                if filtup[list(intup).index(stateli[i1])] == 1:
                    stateli[i1] = stateli[i1]+'(hpf)'
                    xx = sim_x[i1,:].__array__().T
                    wox = np.zeros((tlen,3))
                    lam = 1600
                    xxf = MAT.matrix(hpfilter(xx,wox,tlen,1600,0))
                    sim_x[i1,:] = xxf[0]*100
                elif filtup[list(intup).index(stateli[i1])] == 2:
                    stateli[i1] = stateli[i1]+'(bkf)'
                    xx = sim_x[i1,:].__array__().T
                    wox = np.zeros((tlen,1))
                    up = 6
                    dn = 32
                    kkl = 12
                    xxf = MAT.matrix(bkfilter(xx,up,dn,kkl,tlen))
                    sim_x[i1,:] = xxf[0]*100                  
            # Now hp filter the other variables!
        if self.oswitch:
            for i1 in xrange(sim_o.shape[0]):
                if indo and (i1 in indo) and filtup[list(intup).index(otherli[i1])]:
                    if filtup[list(intup).index(otherli[i1])] == 1:                   
                        otherli[i1] = otherli[i1]+'(hpf)'
                        oo = sim_o[i1,:].__array__().T
                        woo = np.zeros((tlen,3))
                        lam = 1600
                        oof = MAT.matrix(hpfilter(oo,woo,tlen,1600,0))
                    elif filtup[list(intup).index(otherli[i1])] == 2:
                        otherli[i1] = otherli[i1]+'(bkf)'
                        oo = sim_o[i1,:].__array__().T
                        woo = np.zeros((tlen,1))
                        up = 6
                        dn = 32
                        kkl = 12
                        oof = MAT.matrix(bkfilter(oo,up,dn,kkl,tlen)) 

        if indx and indy and indo:
            for x in indx:
                leg.append(stateli[x])
            for y in indy:
                leg.append(conli[y])
            for o in indo:
                leg.append(otherli[o])
            leg = tuple(leg)
            figo = P.figure()
            P.plot(MAT.hstack((sim_x.T[:,indx],sim_y.T[:,indy],sim_o.T[:,indo])).A)
            P.title(str(tlen)+' simulated periods, '+mname)
            P.xlabel('Time')
            P.ylabel('Percentage deviation from SS')
            P.grid()
            P.legend(leg)
        elif not indx and indy and indo:
            for y in indy:
                leg.append(conli[y])
            for o in indo:
                leg.append(otherli[o])
            leg = tuple(leg)
            figo = P.figure()
            P.plot(MAT.hstack((sim_y.T[:,indy],sim_o.T[:,indo])).A)
            P.title(str(tlen)+' simulated periods, '+mname)
            P.xlabel('Time')
            P.ylabel('Percentage deviation from SS')
            P.grid()
            P.legend(leg)
        elif indx and not indy and indo:
            for x in indx:
                leg.append(stateli[x])
            for o in indo:
                leg.append(otherli[o])
            leg = tuple(leg)
            figo = P.figure()
            P.plot(MAT.hstack((sim_x.T[:,indx],sim_o.T[:,indo])).A)
            P.title(str(tlen)+' simulated periods, '+mname)
            P.xlabel('Time')
            P.ylabel('Percentage deviation from SS')
            P.grid()
            P.legend(leg)
        elif indx and indy and not indo:
            for x in indx:
                leg.append(stateli[x])
            for y in indy:
                leg.append(conli[y])
            leg = tuple(leg)
            figo = P.figure()
            P.plot(MAT.hstack((sim_x.T[:,indx],sim_y.T[:,indy])).A)
            P.title(str(tlen)+' simulated periods, '+mname)
            P.xlabel('Time')
            P.ylabel('Percentage deviation from SS')
            P.grid()
            P.legend(leg)
        elif indx and not indy and not indo:
            for x in indx:
                leg.append(stateli[x])
            leg = tuple(leg)
            figo = P.figure()
            P.plot(sim_x.T[:,indx].A)
            P.title(str(tlen)+' simulated periods, '+mname)
            P.xlabel('Time')
            P.ylabel('Percentage deviation from SS')
            P.grid()
            P.legend(leg)
        elif not indx and indy and not indo:
            for y in indy:
                leg.append(conli[y])
            leg = tuple(leg)
            figo = P.figure()
            P.plot(sim_y.T[:,indy].A)
            P.title(str(tlen)+' simulated periods, '+mname)
            P.xlabel('Time')
            P.ylabel('Percentage deviation from SS')
            P.grid()
            P.legend(leg)
        elif not indx and not indy and indo:
            for o in indo:
                leg.append(otherli[o])
            leg = tuple(leg)
            figo = P.figure()
            P.plot(sim_o.T[:,indo].A)
            P.title(str(tlen)+' simulated periods, '+mname)
            P.xlabel('Time')
            P.ylabel('Percentage deviation from SS')
            P.grid()
            P.legend(leg)
        return figo

    def save_sim(self,intup,fpath=None,filtup=None,insim='insim'):
        # Check if simulations have been carried out
        if insim not in dir(self):
            return 'Error: You have not produced any simulations yet! Nothing to graph!'
        if fpath == None:
            return 'Error: You have not supplied the function with an fpath= argument where to save the plot!'
        mname = self.modname
        vardic = self.vardic
        insim = eval('self.'+insim)
        sim_x = COP.deepcopy(insim[0])
        sim_y = COP.deepcopy(insim[1])
        tlen = sim_x.shape[1]
        if self.oswitch:
            sim_o = COP.deepcopy(insim[2])
            nother = self.nother
            otherli = [x[1] for x in vardic['other']['var']]
        nexo = self.nexo
        nendo = self.nendo
        ncon = self.ncon
        conli = [x[1] for x in vardic['con']['var']]
        endoli = [x[1] for x in vardic['endo']['var']]
        exoli = [x[1] for x in vardic['exo']['var']]

        # If filtup is None, create filtup from vardic
        if filtup == None:
            filli = [0]*len(intup)
            for i1,x in enumerate(intup):
                for y in vardic.keys():
                    if x in [z[1] for z in vardic[y]['var']]:
                        indx = [z[1] for z in vardic[y]['var']].index(x)
                        if 'hp' in [z for z in vardic[y]['mod']][indx]:
                            filli[i1] = 1
                        elif 'bk' in [z for z in vardic[y]['mod']][indx]:
                            filli[i1] = 2
            filtup = tuple(filli)


        stateli = exoli+endoli
        alli = stateli+conli
        if self.oswitch:
            alli = alli+otherli
        # Check if all name in intup are available to graph
        for name in intup:
            if name not in alli:
                return 'Error: '+name+' is not a valid variable name for this model!'
        # Create x, y and z indeces
        indx = []
        indy = []
        indo = []
        for name in intup:
            if name in stateli:
                indx.append(stateli.index(name))
            elif name in conli:
                indy.append(conli.index(name))
            elif self.oswitch and name in otherli:
                indo.append(otherli.index(name))
        leg = []
        indx.sort()
        indy.sort()
        indo.sort()     

        # Now hp filter the simulations before graphing according to filtup
        for i1 in xrange(sim_y.shape[0]):
            if indy and (i1 in indy) and filtup[list(intup).index(conli[i1])]:
                if filtup[list(intup).index(conli[i1])] == 1:
                    conli[i1] = conli[i1]+'(hpf)'
                    yy = sim_y[i1,:].__array__().T
                    woy = np.zeros((tlen,3))
                    lam = 1600
                    yyf = MAT.matrix(hpfilter(yy,woy,tlen,1600,0))
                    sim_y[i1,:] = yyf[0]*100
                elif filtup[list(intup).index(conli[i1])] == 2:
                    conli[i1] = conli[i1]+'(bkf)'
                    yy = sim_y[i1,:].__array__().T
                    woy = np.zeros((tlen,1))
                    up = 6
                    dn = 32
                    kkl = 12
                    yyf = MAT.matrix(bkfilter(yy,up,dn,kkl,tlen))
                    sim_y[i1,:] = yyf[0]*100
        # Now filter the state variables!
        for i1 in xrange(sim_x.shape[0]):
            if indx and (i1 in indx) and filtup[list(intup).index(stateli[i1])]:
                if filtup[list(intup).index(stateli[i1])] == 1:
                    stateli[i1] = stateli[i1]+'(hpf)'
                    xx = sim_x[i1,:].__array__().T
                    wox = np.zeros((tlen,3))
                    lam = 1600
                    xxf = MAT.matrix(hpfilter(xx,wox,tlen,1600,0))
                    sim_x[i1,:] = xxf[0]*100
                elif filtup[list(intup).index(stateli[i1])] == 2:
                    stateli[i1] = stateli[i1]+'(bkf)'
                    xx = sim_x[i1,:].__array__().T
                    wox = np.zeros((tlen,1))
                    up = 6
                    dn = 32
                    kkl = 12
                    xxf = MAT.matrix(bkfilter(xx,up,dn,kkl,tlen))
                    sim_x[i1,:] = xxf[0]*100                  
            # Now hp filter the other variables!
        if self.oswitch:
            for i1 in xrange(sim_o.shape[0]):
                if indo and (i1 in indo) and filtup[list(intup).index(otherli[i1])]:
                    if filtup[list(intup).index(otherli[i1])] == 1:                   
                        otherli[i1] = otherli[i1]+'(hpf)'
                        oo = sim_o[i1,:].__array__().T
                        woo = np.zeros((tlen,3))
                        lam = 1600
                        oof = MAT.matrix(hpfilter(oo,woo,tlen,1600,0))
                    elif filtup[list(intup).index(otherli[i1])] == 2:
                        otherli[i1] = otherli[i1]+'(bkf)'
                        oo = sim_o[i1,:].__array__().T
                        woo = np.zeros((tlen,1))
                        up = 6
                        dn = 32
                        kkl = 12
                        oof = MAT.matrix(bkfilter(oo,up,dn,kkl,tlen)) 

        if indx and indy and indo:
            for x in indx:
                leg.append(stateli[x])
            for y in indy:
                leg.append(conli[y])
            for o in indo:
                leg.append(otherli[o])
            leg = tuple(leg)
            figo = P.figure()
            P.plot(MAT.hstack((sim_x.T[:,indx],sim_y.T[:,indy],sim_o.T[:,indo])).A)
            P.title(str(tlen)+' simulated periods, '+mname)
            P.xlabel('Time')
            P.ylabel('Percentage deviation from SS')
            P.grid()
            P.legend(leg)
        elif not indx and indy and indo:
            for y in indy:
                leg.append(conli[y])
            for o in indo:
                leg.append(otherli[o])
            leg = tuple(leg)
            figo = P.figure()
            P.plot(MAT.hstack((sim_y.T[:,indy],sim_o.T[:,indo])).A)
            P.title(str(tlen)+' simulated periods, '+mname)
            P.xlabel('Time')
            P.ylabel('Percentage deviation from SS')
            P.grid()
            P.legend(leg)
        elif indx and not indy and indo:
            for x in indx:
                leg.append(stateli[x])
            for o in indo:
                leg.append(otherli[o])
            leg = tuple(leg)
            figo = P.figure()
            P.plot(MAT.hstack((sim_x.T[:,indx],sim_o.T[:,indo])).A)
            P.title(str(tlen)+' simulated periods, '+mname)
            P.xlabel('Time')
            P.ylabel('Percentage deviation from SS')
            P.grid()
            P.legend(leg)
        elif indx and indy and not indo:
            for x in indx:
                leg.append(stateli[x])
            for y in indy:
                leg.append(conli[y])
            leg = tuple(leg)
            figo = P.figure()
            P.plot(MAT.hstack((sim_x.T[:,indx],sim_y.T[:,indy])).A)
            P.title(str(tlen)+' simulated periods, '+mname)
            P.xlabel('Time')
            P.ylabel('Percentage deviation from SS')
            P.grid()
            P.legend(leg)
        elif indx and not indy and not indo:
            for x in indx:
                leg.append(stateli[x])
            leg = tuple(leg)
            figo = P.figure()
            P.plot(sim_x.T[:,indx].A)
            P.title(str(tlen)+' simulated periods, '+mname)
            P.xlabel('Time')
            P.ylabel('Percentage deviation from SS')
            P.grid()
            P.legend(leg)
        elif not indx and indy and not indo:
            for y in indy:
                leg.append(conli[y])
            leg = tuple(leg)
            figo = P.figure()
            P.plot(sim_y.T[:,indy].A)
            P.title(str(tlen)+' simulated periods, '+mname)
            P.xlabel('Time')
            P.ylabel('Percentage deviation from SS')
            P.grid()
            P.legend(leg)
        elif not indx and not indy and indo:
            for o in indo:
                leg.append(otherli[o])
            leg = tuple(leg)
            figo = P.figure()
            P.plot(sim_o.T[:,indo].A)
            P.title(str(tlen)+' simulated periods, '+mname)
            P.xlabel('Time')
            P.ylabel('Percentage deviation from SS')
            P.grid()
            P.legend(leg)
        PLT.savefig(fpath,dpi=100)
        return "Your plot has been saved in: "+fpath


    def irf(self,tlen,sntup):
        tlen = tlen + 1
        ncon = self.ncon
        nexo = self.nexo
        nendo = self.nendo
        tstates = self.tstates
        sigma = self.sigma
        ssigma = self.ssigma
        if self.oswitch:
            numjl = self.numjl
            numhl = self.numhl
        kx = self.KX
        ky = self.KY
        pp = self.P
        ff = self.F
        ee = self.E
        gg = self.G

        sposli=[]
        exoli = [x[1] for x in self.vardic['exo']['var']]
        # Check if names are valid
        for name in sntup:
            if name not in exoli:
                return 'Error: '+name+' is not a valid exoshock name for this model!'
        for name in sntup:
            sposli.append(exoli.index(name))
        # Expose spos choice to self for show_irf
        self.spos = (sntup,sposli)

        shock = MAT.zeros((nexo,1))
        sendo = MAT.zeros((nendo,1))

        for spos in sposli:
            shock[spos,0] = 1.0
        shock = MAT.vstack((shock,sendo))

        x_one_m1 = shock
        x_one_0 = pp*x_one_m1
        x_two_m1 = shock
        y_one_0 = ff*x_one_m1
        y_one_m1 = MAT.zeros(y_one_0.shape)
        y_two_0 = 0.5*MAT.kron(MAT.eye(ncon),x_one_m1.T)*ee*x_one_m1
        if self.oswitch:
            nother = self.nother
            o_one_0 = numjl*MAT.vstack((x_one_0,y_one_0,x_one_m1,y_one_m1))
            o_two_0 = numjl*MAT.vstack((x_one_0,y_one_0,x_one_m1,y_one_m1))+\
                0.5*MAT.kron(MAT.eye(nother),MAT.vstack((x_one_0,y_one_0,x_one_m1,y_one_m1)).T)*\
                numhl*MAT.vstack((x_one_0,y_one_0,x_one_m1,y_one_m1))

        x_one_c = COP.deepcopy(x_one_m1)
        y_one_c = COP.deepcopy(y_one_0)
        x_two_c = COP.deepcopy(x_two_m1)
        y_two_c = COP.deepcopy(y_two_0)
        if self.oswitch:
            o_one_c = COP.deepcopy(o_one_0)
            o_two_c = COP.deepcopy(o_two_0)

        x_one = COP.deepcopy(x_one_c)
        y_one = COP.deepcopy(y_one_c)
        x_two = COP.deepcopy(x_two_c)
        y_two = COP.deepcopy(y_two_c)
        if self.oswitch:
            o_one = COP.deepcopy(o_one_c)
            o_two = COP.deepcopy(o_two_c)

        for i1 in range(tlen):
            x_one_n = pp*x_one_c
            y_one_n = ff*x_one_c
            x_two_n = pp*x_two_c+0.5*MAT.kron(MAT.eye(tstates),x_one_c.T)*gg*x_one_c
            y_two_n = ff*x_two_c+0.5*MAT.kron(MAT.eye(ncon),x_one_c.T)*ee*x_one_c
            if self.oswitch:
                o_one_n = numjl*MAT.vstack((x_one_n,y_one_n,x_one_c,y_one_c))
                o_two_n = numjl*MAT.vstack((x_one_n,y_one_n,x_one_c,y_one_c))+\
                    0.5*MAT.kron(MAT.eye(nother),MAT.vstack((x_one_n,y_one_n,x_one_c,y_one_c)).T)*\
                    numhl*MAT.vstack((x_one_n,y_one_n,x_one_c,y_one_c))

            x_one = MAT.hstack((x_one,x_one_c))
            y_one = MAT.hstack((y_one,y_one_n))
            x_two = MAT.hstack((x_two,x_two_c))
            y_two = MAT.hstack((y_two,y_two_n))
            if self.oswitch:
                o_one = MAT.hstack((o_one,o_one_n))
                o_two = MAT.hstack((o_two,o_two_n))

            x_one_c = COP.deepcopy(x_one_n)
            y_one_c = COP.deepcopy(y_one_n)
            x_two_c = COP.deepcopy(x_one_n)
            y_two_c = COP.deepcopy(y_two_n)

        self.irf_x_two = x_two[:,1:-1]
        self.irf_y_two = y_two[:,1:-1]
        self.inirf = [self.irf_x_two,self.irf_y_two]
        if self.oswitch:
            self.irf_o_one = o_one[:,2:]
            self.irf_o_two = o_two[:,2:]
            self.inirf = self.inirf + [self.irf_o_two,]

    def show_irf(self,intup,inirf='inirf'):
        # Check if simulations have been carried out
        if inirf not in dir(self):
            return 'Error: You have not produced any IRFs yet! Nothing to graph!'
        inirf = eval('self.'+inirf)
        irf_x = COP.deepcopy(inirf[0])
        tlen = irf_x.shape[1]
        irf_x = MAT.hstack((MAT.zeros((irf_x.shape[0],20)),irf_x))
        irf_y = COP.deepcopy(inirf[1])
        irf_y = MAT.hstack((MAT.zeros((irf_y.shape[0],20)),irf_y))
        irf_x = irf_x*100
        irf_y = irf_y*100
        mname = self.modname
        vardic = self.vardic
        time_axis = np.arange(-20,tlen,1)
        if self.oswitch:
            irf_o = COP.deepcopy(inirf[2])
            nother = self.nother
            varother = self.vardic['other']['var']
            otherli = [x[1] for x in varother]
        nexo = self.nexo
        nendo = self.nendo
        ncon = self.ncon
        conli = [x[1] for x in vardic['con']['var']]
        endoli = [x[1] for x in vardic['endo']['var']]
        exoli = [x[1] for x in vardic['exo']['var']]

        stateli = exoli+endoli
        alli = stateli+conli
        if self.oswitch:
            alli = alli+otherli
        # Check if all name in intup are available to graph
        for name in intup:
            if name not in alli:
                return 'Error: '+name+' is not a valid variable name for this model!'
        # Create x, y and z indeces
        indx = []
        indy = []
        indo = []
        for name in intup:
            if name in stateli:
                indx.append(stateli.index(name))
            elif name in conli:
                indy.append(conli.index(name))
            elif self.oswitch and name in otherli:
                indo.append(otherli.index(name))
        leg = []
        indx.sort()
        indy.sort()
        indo.sort()

        if indx and indy and indo:
            for x in indx:
                leg.append(stateli[x])
            for y in indy:
                leg.append(conli[y])
            for o in indo:
                leg.append(otherli[o])
            leg = tuple(leg)
            figo = P.figure()
            ax = figo.add_subplot(111)
            ax.set_xlim([-20,tlen])
            ax.plot(time_axis,MAT.hstack((irf_x.T[:,indx],irf_y.T[:,indy],irf_o.T[:,indo])).A)
            P.title(str(tlen)+' simulated IRF periods, '+mname)
            P.xlabel('Time')
            P.ylabel('Percentage Deviation from SS')
            P.grid()
            P.legend(leg)
        elif not indx and indy and indo:
            for y in indy:
                leg.append(conli[y])
            for o in indo:
                leg.append(otherli[o])
            leg = tuple(leg)
            figo = P.figure()
            ax = figo.add_subplot(111)
            ax.set_xlim([-20,tlen])
            ax.plot(time_axis,MAT.hstack((irf_y.T[:,indy],irf_o.T[:,indo])).A)
            P.title(str(tlen)+' simulated IRF periods, '+mname)
            P.xlabel('Time')
            P.ylabel('Percentage Deviation from SS')
            P.grid()
            P.legend(leg)
        elif indx and not indy and indo:
            for x in indx:
                leg.append(stateli[x])
            for o in indo:
                leg.append(otherli[o])
            leg = tuple(leg)
            figo = P.figure()
            ax = figo.add_subplot(111)
            ax.set_xlim([-20,tlen])
            ax.plot(time_axis,MAT.hstack((irf_x.T[:,indx],irf_o.T[:,indo])).A)
            P.title(str(tlen)+' simulated IRF periods, '+mname)
            P.xlabel('Time')
            P.ylabel('Percentage Deviation from SS')
            P.grid()
            P.legend(leg)
        elif indx and indy and not indo:
            for x in indx:
                leg.append(stateli[x])
            for y in indy:
                leg.append(conli[y])
            leg = tuple(leg)
            figo = P.figure()
            ax = figo.add_subplot(111)
            ax.set_xlim([-20,tlen])
            ax.plot(time_axis,MAT.hstack((irf_x.T[:,indx],irf_y.T[:,indy])).A)
            P.title(str(tlen)+' simulated IRF periods, '+mname)
            P.xlabel('Time')
            P.ylabel('Percentage Deviation from SS')
            P.grid()
            P.legend(leg)
        elif indx and not indy and not indo:
            for x in indx:
                leg.append(stateli[x])
            leg = tuple(leg)
            figo = P.figure()
            ax = figo.add_subplot(111)
            ax.set_xlim([-20,tlen])
            ax.plot(time_axis,irf_x.T[:,indx].A)
            P.title(str(tlen)+' simulated IRF periods, '+mname)
            P.xlabel('Time')
            P.ylabel('Percentage Deviation from SS')
            P.grid()
            P.legend(leg)
        elif not indx and indy and not indo:
            for y in indy:
                leg.append(conli[y])
            leg = tuple(leg)
            figo = P.figure()
            ax = figo.add_subplot(111)
            ax.set_xlim([-20,tlen])
            ax.plot(time_axis,irf_y.T[:,indy].A)
            P.title(str(tlen)+' simulated IRF periods, '+mname)
            P.xlabel('Time')
            P.ylabel('Percentage Deviation from SS, hp-filtered')
            P.grid()
            P.legend(leg)
        elif not indx and not indy and indo:
            for o in indo:
                leg.append(otherli[o])
            leg = tuple(leg)
            figo = P.figure()
            ax = figo.add_subplot(111)
            ax.set_xlim([-20,tlen])
            ax.plot(time_axis,irf_o.T[:,indo].A)
            P.title(str(tlen)+' simulated IRF periods, '+mname)
            P.xlabel('Time')
            P.ylabel('Percentage Deviation from SS, hp-filtered')
            P.grid()
            P.legend(leg)
        return figo

    def save_irf(self,intup,fpath=None,inirf='inirf'):
        # Check if simulations have been carried out
        if inirf not in dir(self):
            return 'Error: You have not produced any IRFs yet! Nothing to graph!'
        if fpath == None:
            return 'Error: You have not supplied the function with an fpath= argument where to save the plot!'
        inirf = eval('self.'+inirf)
        irf_x = COP.deepcopy(inirf[0])
        tlen = irf_x.shape[1]
        irf_x = MAT.hstack((MAT.zeros((irf_x.shape[0],20)),irf_x))
        irf_y = COP.deepcopy(inirf[1])
        irf_y = MAT.hstack((MAT.zeros((irf_y.shape[0],20)),irf_y))
        irf_x = irf_x*100
        irf_y = irf_y*100
        mname = self.modname
        vardic = self.vardic
        time_axis = np.arange(-20,tlen,1)
        if self.oswitch:
            irf_o = COP.deepcopy(inirf[2])
            nother = self.nother
            varother = self.vardic['other']['var']
            otherli = [x[1] for x in varother]
        nexo = self.nexo
        nendo = self.nendo
        ncon = self.ncon
        conli = [x[1] for x in vardic['con']['var']]
        endoli = [x[1] for x in vardic['endo']['var']]
        exoli = [x[1] for x in vardic['exo']['var']]

        stateli = exoli+endoli
        alli = stateli+conli
        if self.oswitch:
            alli = alli+otherli
        # Check if all name in intup are available to graph
        for name in intup:
            if name not in alli:
                return 'Error: '+name+' is not a valid variable name for this model!'
        # Create x, y and z indeces
        indx = []
        indy = []
        indo = []
        for name in intup:
            if name in stateli:
                indx.append(stateli.index(name))
            elif name in conli:
                indy.append(conli.index(name))
            elif self.oswitch and name in otherli:
                indo.append(otherli.index(name))
        leg = []
        indx.sort()
        indy.sort()
        indo.sort()

        if indx and indy and indo:
            for x in indx:
                leg.append(stateli[x])
            for y in indy:
                leg.append(conli[y])
            for o in indo:
                leg.append(otherli[o])
            leg = tuple(leg)
            figo = P.figure()
            ax = figo.add_subplot(111)
            ax.set_xlim([-20,tlen])
            ax.plot(time_axis,MAT.hstack((irf_x.T[:,indx],irf_y.T[:,indy],irf_o.T[:,indo])).A)
            P.title(str(tlen)+' simulated IRF periods, '+mname)
            P.xlabel('Time')
            P.ylabel('Percentage Deviation from SS')
            P.grid()
            P.legend(leg)
        elif not indx and indy and indo:
            for y in indy:
                leg.append(conli[y])
            for o in indo:
                leg.append(otherli[o])
            leg = tuple(leg)
            figo = P.figure()
            ax = figo.add_subplot(111)
            ax.set_xlim([-20,tlen])
            ax.plot(time_axis,MAT.hstack((irf_y.T[:,indy],irf_o.T[:,indo])).A)
            P.title(str(tlen)+' simulated IRF periods, '+mname)
            P.xlabel('Time')
            P.ylabel('Percentage Deviation from SS')
            P.grid()
            P.legend(leg)
        elif indx and not indy and indo:
            for x in indx:
                leg.append(stateli[x])
            for o in indo:
                leg.append(otherli[o])
            leg = tuple(leg)
            figo = P.figure()
            ax = figo.add_subplot(111)
            ax.set_xlim([-20,tlen])
            ax.plot(time_axis,MAT.hstack((irf_x.T[:,indx],irf_o.T[:,indo])).A)
            P.title(str(tlen)+' simulated IRF periods, '+mname)
            P.xlabel('Time')
            P.ylabel('Percentage Deviation from SS')
            P.grid()
            P.legend(leg)
        elif indx and indy and not indo:
            for x in indx:
                leg.append(stateli[x])
            for y in indy:
                leg.append(conli[y])
            leg = tuple(leg)
            figo = P.figure()
            ax = figo.add_subplot(111)
            ax.set_xlim([-20,tlen])
            ax.plot(time_axis,MAT.hstack((irf_x.T[:,indx],irf_y.T[:,indy])).A)
            P.title(str(tlen)+' simulated IRF periods, '+mname)
            P.xlabel('Time')
            P.ylabel('Percentage Deviation from SS')
            P.grid()
            P.legend(leg)
        elif indx and not indy and not indo:
            for x in indx:
                leg.append(stateli[x])
            leg = tuple(leg)
            figo = P.figure()
            ax = figo.add_subplot(111)
            ax.set_xlim([-20,tlen])
            ax.plot(time_axis,irf_x.T[:,indx].A)
            P.title(str(tlen)+' simulated IRF periods, '+mname)
            P.xlabel('Time')
            P.ylabel('Percentage Deviation from SS')
            P.grid()
            P.legend(leg)
        elif not indx and indy and not indo:
            for y in indy:
                leg.append(conli[y])
            leg = tuple(leg)
            figo = P.figure()
            ax = figo.add_subplot(111)
            ax.set_xlim([-20,tlen])
            ax.plot(time_axis,irf_y.T[:,indy].A)
            P.title(str(tlen)+' simulated IRF periods, '+mname)
            P.xlabel('Time')
            P.ylabel('Percentage Deviation from SS, hp-filtered')
            P.grid()
            P.legend(leg)
        elif not indx and not indy and indo:
            for o in indo:
                leg.append(otherli[o])
            leg = tuple(leg)
            figo = P.figure()
            ax = figo.add_subplot(111)
            ax.set_xlim([-20,tlen])
            ax.plot(time_axis,irf_o.T[:,indo].A)
            P.title(str(tlen)+' simulated IRF periods, '+mname)
            P.xlabel('Time')
            P.ylabel('Percentage Deviation from SS, hp-filtered')
            P.grid()
            P.legend(leg)
        PLT.savefig(fpath,dpi=100)
        return "Your plot has been save in: "+fpath

#----------------------------------------------------------------------------------------------------------------------
class MatKlein2D(PyKlein2D):

    def __init__(self,intup):
        self.sess1 = intup[-1]
        intup2 = intup[:-1]
        # Get all PyKlein2D attributes
        PyKlein2D.__init__(self, intup2)

    def solve(self):
        tstates = self.tstates
        sess1 = self.sess1
        ssigma = self.ssigma
        mlabraw.eval(sess1,'clear all;')
        mlabraw.eval(sess1,'cd '+mlabpath)
        mlabraw.eval(sess1,'cd Klein')
        mlabraw.put(sess1,'jac',self.gra)
        mlabraw.put(sess1,'hess',self.hes)
        mlabraw.put(sess1,'nstates',self.tstates)
        mlabraw.put(sess1,'ssigma',self.ssigma)
        mlabraw.eval(sess1,'[ff,pp,ee,gg,kx,ky] = solab2(jac,hess,ssigma,nstates)')
        self.F = np.matrix(mlabraw.get(sess1,'ff'))
        self.P = np.matrix(mlabraw.get(sess1,'pp'))
        self.E = np.matrix(mlabraw.get(sess1,'ee'))
        self.G = np.matrix(mlabraw.get(sess1,'gg'))
        self.KX = np.matrix(mlabraw.get(sess1,'kx'))
        self.KY = np.matrix(mlabraw.get(sess1,'ky'))
#----------------------------------------------------------------------------------------------------------------------
class ForKleinD(PyKlein2D):

    def __init__(self,intup):
        self.gra = intup[0]
        self.nendo = intup[1]
        self.nexo = intup[2]
        self.ncon = intup[3]
        self.sigma = intup[4]
        self.A = intup[5]
        self.B = intup[6]
        self.vardic = intup[7]
        self.vdic = intup[8]
        self.modname = intup[9]
        self.audic = intup[10]
        if self.vardic['other']['var']:
            self.numjl = intup[11]
            self.nother = intup[12]
            self.oswitch = 1
        else:
            self.oswitch = 0
        self.tstates = self.nendo+self.nexo
        self.ssigma = self.mkssigma(self.tstates,self.nexo,self.sigma)

    def solve(self):
        A = self.A
        B = self.B
        tstates = self.tstates
        (F,P,retcon) = isolab(A,B,tstates,MAT.shape(A)[0])
        if MAT.sum(P.reshape(-1,1)) == 0.0:
            return
        else:
            self.P = np.matrix(P)
            self.F = np.matrix(F)

    def sim(self,tlen,sntup=None):
        # Add 1000 observations, as they will be thrown away
        # Add one more observation to start first-order vector
        exoli = [x[1] for x in self.vardic['exo']['var']]
        indx=[]
        if sntup == None:
            indx = range(len(exoli))
        else:
            for name in sntup:
                if name not in exoli:
                    return 'Error: '+name+' is not a valid exo variable for this model!'
                else:
                    indx.append(exoli.index(name))
        indx.sort()
        ncon = self.ncon
        nexo = self.nexo
        nendo = self.nendo
        tstates = self.tstates
        tlena = 1000+tlen
        sigma = self.sigma
        ssigma = self.ssigma
        if self.oswitch:
            numjl = self.numjl

        pp = self.P
        ff = self.F

        count = 0
        for varia in MAT.diag(sigma):
            if locals().has_key('ranvec'):
                if count in indx:
                    ranvec = MAT.vstack((ranvec,np.sqrt(varia)*MAT.matrix(np.random.standard_normal(tlena))))
                else:
                    ranvec = MAT.vstack((ranvec,MAT.zeros((1,tlena))))      
            else:
                if count in indx:
                    ranvec = np.sqrt(varia)*MAT.matrix(np.random.standard_normal(tlena))
                else:
                    ranvec = MAT.zeros((1,tlena))
            count = count + 1

        ranvec = MAT.vstack((ranvec,MAT.zeros((nendo,tlena))))

        x_one_m1 = ranvec[:,0]
        y_one_0 = ff*x_one_m1
        y_one_m1 = MAT.zeros(y_one_0.shape)
        x_one_0 = pp*x_one_m1
        if self.oswitch:
            nother = self.nother
            o_one_0 = numjl*MAT.vstack((x_one_0,y_one_0,x_one_m1,y_one_m1))

        x_one_c = COP.deepcopy(x_one_m1)
        y_one_c = COP.deepcopy(y_one_0)
        if self.oswitch:
            o_one_c = COP.deepcopy(o_one_0)

        x_one = COP.deepcopy(x_one_c)
        y_one = COP.deepcopy(y_one_c)
        if self.oswitch:
            o_one = COP.deepcopy(o_one_c)

        for i1 in range(1,ranvec.shape[1],1):

            x_one_n = pp*x_one_c+ranvec[:,i1]
            y_one_n = ff*x_one_c
            if self.oswitch:
                o_one_n = numjl*MAT.vstack((x_one_n,y_one_n,x_one_c,y_one_c))

            x_one = MAT.hstack((x_one,x_one_c))
            y_one = MAT.hstack((y_one,y_one_n))
            if self.oswitch:
                o_one = MAT.hstack((o_one,o_one_n))

            x_one_c = x_one_n
            y_one_c = y_one_n

        # Throw away first 1000 obs
        x_one = x_one[:,1000:]
        y_one = y_one[:,1000:]
        if self.oswitch:
            o_one = o_one[:,1000:]

        self.sim_x_one = x_one
        self.sim_y_one = y_one
        self.insim = [self.sim_x_one,self.sim_y_one]
        if self.oswitch:
            self.sim_o_one = o_one
            self.insim = self.insim + [self.sim_o_one,]

    def irf(self,tlen,sntup):
        tlen = tlen + 1
        ncon = self.ncon
        nexo = self.nexo
        nendo = self.nendo
        tstates = self.tstates
        sigma = self.sigma
        ssigma = self.ssigma
        tlen = tlen
        if self.oswitch:
            numjl = self.numjl

        pp = self.P
        ff = self.F


        sposli=[]
        exoli = [x[1] for x in self.vardic['exo']['var']]
        # Check if names are valid
        for name in sntup:
            if name not in exoli:
                return 'Error: '+name+' is not a valid exoshock name for this model!'
        for name in sntup:
            sposli.append(exoli.index(name))
        # Expose spos choice to self for show_irf
        self.spos = (sntup,sposli)

        shock = MAT.zeros((nexo,1))
        sendo = MAT.zeros((nendo,1))

        for spos in sposli:
            shock[spos,0] = 1.0
        shock = MAT.vstack((shock,sendo))

        x_one_m1 = shock
        y_one_0 = ff*x_one_m1
        y_one_m1 = MAT.zeros(y_one_0.shape)
        x_one_0 = pp*x_one_m1
        if self.oswitch:
            nother = self.nother
            o_one_0 = numjl*MAT.vstack((x_one_0,y_one_0,x_one_m1,y_one_m1))

        x_one_c = COP.deepcopy(x_one_m1)
        y_one_c = COP.deepcopy(y_one_0)
        if self.oswitch:
            o_one_c = COP.deepcopy(o_one_0)

        x_one = COP.deepcopy(x_one_c)
        y_one = COP.deepcopy(y_one_c)
        if self.oswitch:
            o_one = COP.deepcopy(o_one_c)

        for i1 in range(tlen):
            x_one_n = pp*x_one_c
            y_one_n = ff*x_one_c
            if self.oswitch:
                o_one_n = numjl*MAT.vstack((x_one_n,y_one_n,x_one_c,y_one_c))

            x_one = MAT.hstack((x_one,x_one_c))
            y_one = MAT.hstack((y_one,y_one_n))
            if self.oswitch:
                o_one = MAT.hstack((o_one,o_one_n))

            x_one_c = x_one_n
            y_one_c = y_one_n

        # Throw away first observation
        self.irf_x_one = x_one[:,1:-1]
        self.irf_y_one = y_one[:,1:-1]
        self.inirf = [self.irf_x_one,self.irf_y_one]
        if self.oswitch:
            self.irf_o_one = o_one[:,2:]
            self.inirf = self.inirf + [self.irf_o_one,]

#------------------------currently not called and really not working, removed from init----------------
class FairTaylor:

    def __init__(self,algtype='type1',intup=None):
        self.algtype = algtype
        self.data = intup[0]
        self.param = intup[1]
        self.sstates_list = intup[2]
        self.vardic = intup[3]
        self.vardic2 = intup[4]
        self.modeq = intup[5]
        self.maxlags = intup[6]
        self.maxleads = intup[7]
        self.maxshocks = intup[8]
        self.maxinfosets = intup[9]
        self.shock_vars = intup[10]
        self.iid_vars = intup[11]
        self.vars = intup[12]
        self.re_var = intup[13]
        self.re_var2 = intup[14]
        self.sstate = intup[15]

        self.prepdat(self.data)
        self.prepmodeq(self.modeq)

    def prepdat(self,data=None):
        self.cur_pres = {}
        self.cur_past = {}
        self.cur_fut = {}
        for x1 in data.items():
            self.cur_pres[x1[0]] = x1[1][self.maxlags:len(x1[1])-self.maxleads]
            self.cur_past[x1[0]] = x1[1][0:-2]
            self.cur_fut[x1[0]] = x1[1][2:]

    def prepmodeq(self,modeq=None):
        re_var2 = self.re_var2
        self.modeq1 = COP.deepcopy(modeq)
        tmp_list = []
        i1 = 0
        for x1 in modeq:
            itera = re_var2.finditer(x1)
            for x2 in itera:
                if x2.group('svar'):
                    tmp_list = tmp_list + [[i1,x2.group('svar'),x2.start(),x2.end()],]
            i1 = i1 + 1
        tmp_list.reverse()
        if tmp_list:
            for x2 in tmp_list:
                i1 = x2[0]
                expr = x2[1]
                estart = x2[2]
                eend = x2[3]
                x1 = self.modeq1[i1][0:estart]+expr.capitalize()+\
                   '_bar'+self.modeq1[i1][eend:]
                self.modeq1[i1] = x1
        self.modeq2 = self.modeq1[0:len(modeq)-self.maxshocks]


        self.modeq3 = COP.deepcopy(self.modeq2)
        # Create varlist from vardic to establish fixed order
        self.varlist = self.vardic.items()
        # Create ordered vars and varnames
        varnames = []
        variables = []
        sub_list1 = []
        sub_list2 = []
        tmp_index = {}
        for x1 in self.varlist:
            varnames = varnames + [x1[1],]
            variables = variables + [x1[0],]
        self.varnames = varnames
        self.variables = variables
        re_var2 = self.re_var2
        i1 = 0
        i2 = 0
        for x1 in self.modeq2:
            itera = re_var2.finditer(x1)
            for x2 in itera:
                if x2.group('vvar') and not x2.group('exp') and not x2.group('lagt'):
                    tmp_match = variables.index(x2.group('var'))
                    if not tmp_index.has_key(x2.group('var')):
                        tmp_index[x2.group('var')] = (i2,x2.group(0))
                        i2 = i2 + 1
                    sub_list1 = sub_list1 + [['invar['+str(tmp_index[x2.group('var')][0])+']',
                                  x2.start(),x2.end(),x2.group(0),tmp_match,i1],]

            sub_list1.reverse()
            if sub_list1:
                for x4 in sub_list1:
                    str_tmp = x4[0]
                    pstart = x4[1]
                    pend = x4[2]
                    self.modeq3[i1] = self.modeq3[i1][0:pstart]+str_tmp+self.modeq3[i1][pend:]
                sub_list2 = sub_list2 + [sub_list1,]
                sub_list1 = []
            i1 = i1 + 1
        self.index = tmp_index
        # Create inverted index2
        index2 = {}
        for x1 in self.index.items():
            index2[x1[1][0]] = (x1[0],x1[1][1])
        self.index2 = index2
        return sub_list2

    def makecur(self,tpos,curlag,curpres,curfut):
        lag_dic={}
        pres_dic={}
        fut_dic={}
        all_dic={}
        for x1 in curlag.items():
            if float(x1[1][tpos].data) > 0:
                lag_dic[self.vardic2[x1[0]]+'_L'] = float(x1[1][tpos].data)
            else:
                lag_dic[self.vardic2[x1[0]]+'_L'] = 0.01
        for x1 in curpres.items():
            if float(x1[1][tpos].data) > 0:
                pres_dic[self.vardic2[x1[0]]+'_N'] = float(x1[1][tpos].data)
            else:
                pres_dic[self.vardic2[x1[0]]+'_N'] = 0.01
        for x1 in curfut.items():
            if float(x1[1][tpos].data) > 0:
                fut_dic['INFO_N_'+self.vardic2[x1[0]]+'_F'] = float(x1[1][tpos].data)
            else:
                fut_dic['INFO_N_'+self.vardic2[x1[0]]+'_F'] = 0.01
        all_dic.update(lag_dic)
        all_dic.update(pres_dic)
        all_dic.update(fut_dic)
        self.alldic =all_dic
        return all_dic

    def solveone(self,tpos,curlag,curpres,curfut):

        #Define the function to be handed over
        #to fsolve

        def func(invar):
            locals().update(self.param)
            locals().update(self.sstate[0])
            locals().update(self.makecur(tpos,self.cur_past,self.cur_pres,self.cur_fut))
            fdot1 = np.zeros((len(self.modeq3)),'d')
            i1=0
            for x in self.modeq3:
                fdot1[i1] = eval(x)
                i1 = i1 + 1
            return fdot1


        #def func(invar):
            #locals().update(self.param)
            #locals().update(self.sstate[0])
            #locals().update(self.makecur(tpos,self.cur_past,self.cur_pres,self.cur_fut))
            #fdot1 = np.zeros((len(self.modeq3)),'d')
            #i1=0
            #for x in self.modeq3:
                #fdot1[i1] = abs(eval(x))
                #i1 = i1 + 1
            #return sum(fdot1)

        #def fprime(invar):
            #return np.array(([1,-1]))


        # Define the initial values and
        # start the non-linear solver
        init_val = len(self.index)*[0,]
        for x1 in self.index.items():
            varia = self.vardic[x1[0]]['var']
            init_val[x1[1][0]] = float(curpres[varia][tpos].data)

        # Determine bounds
        #in_bounds = len(self.index)*[(0.01,None),]

        (output,infodict,ier,mesg) = O.fsolve(func,init_val,full_output=1)

        #(output,f_out,d_out) = O.fmin_l_bfgs_b(func,init_val,
                                                            #fprime,approx_grad=True,bounds=in_bounds)


        # Attach the outputs of the solver as attributes
        fsout={}
        self.output = output
        i1 = 0
        for x1 in self.index2.items():
            fsout[x1[1][1]] = (output[x1[0]],x1[1][0])
            i1 = i1 + 1
        self.fsout = fsout
        self.output = output
        self.infodict = infodict
        self.ier = ier
        self.mesg = mesg

        return fsout

    def solveall(self):
        # Calculate initial convergence criterion
        criterion = 10
        loop_c = 0
        while criterion > 0.01:
            cur_past_t = {}
            cur_pres_t = {}
            cur_fut_t = {}
            for x1 in self.vardic2.items():
                cur_past_t[x1[0]] = np.zeros(len(self.cur_pres.items()[0][1]))
                cur_past_t[x1[0]][0] = float(self.cur_past[x1[0]][0].data)
                cur_pres_t[x1[0]] = np.zeros(len(self.cur_pres.items()[0][1]))
                cur_fut_t[x1[0]] = np.zeros(len(self.cur_pres.items()[0][1]))
                cur_fut_t[x1[0]][-1] = float(self.cur_fut[x1[0]][-1].data)
            for i1 in range(0,len(self.cur_pres.items()[0][1])):
                out_tmp = self.solveone(i1,self.cur_past,self.cur_pres,self.cur_fut)
                for x2 in out_tmp.items():
                    # Standard
                    if self.algtype == 'type1':
                        cur_pres_t[self.vardic[x2[1][1]['var']]][i1] = x2[1][0]
                    # Fast-Gauss Seidel
                    elif self.algtype == 'type2':
                        cur_pres_t[self.vardic[x2[1][1]['var']]][i1] = x2[1][0]
                        try:
                            self.cur_past[self.vardic[x2[1][1]['var']]][i1+1] = x2[1][0]
                        except:
                            pass

            # Recalculate convergence criterion
            cr_list = [0,]*len(self.vardic)
            va_list = [0,]*len(self.vardic)
            for x1,x2 in zip(self.vardic.items(),range(0,len(self.vardic),1)):
                cr_list[x2] = cr_list[x2] + sum(abs(cur_fut_t[x1[1]][0:-1]-cur_pres_t[x1[1]][1:]))
                va_list[x2] = x1[1]
            criterion = sum(cr_list)
            loop_c = loop_c + 1
            print ('Loop: ',loop_c)
            print ('Var:  ',va_list)
            print ('Crit: ',cr_list)


            for x1 in self.vardic2.items():
                cur_past_t[x1[0]][1:] = cur_pres_t[x1[0]][:-1]
                cur_fut_t[x1[0]][0:-1] = cur_pres_t[x1[0]][1:]

            for x1,x2,x3 in zip(cur_past_t.items(),cur_pres_t.items(),cur_fut_t.items()):
                self.cur_past[x1[0]] = TSS.time_series\
                    (x1[1],start_date=TSS.Date(freq=self.cur_past[x1[0]].start_date.freqstr,
                                   year=self.cur_past[x1[0]].start_date.year,
                                   quarter=self.cur_past[x1[0]].start_date.quarter),
                                   freq=self.cur_past[x1[0]].start_date.freqstr)

                self.cur_pres[x1[0]] = TSS.time_series\
                    (x2[1],start_date=TSS.Date(freq=self.cur_pres[x1[0]].start_date.freqstr,
                                   year=self.cur_pres[x1[0]].start_date.year,
                                   quarter=self.cur_pres[x1[0]].start_date.quarter),
                                   freq=self.cur_pres[x1[0]].start_date.freqstr)

                self.cur_fut[x1[0]] = TSS.time_series\
                    (x3[1],start_date=TSS.Date(freq=self.cur_fut[x1[0]].start_date.freqstr,
                                   year=self.cur_fut[x1[0]].start_date.year,
                                   quarter=self.cur_fut[x1[0]].start_date.quarter),
                                   freq=self.cur_fut[x1[0]].start_date.freqstr)
