Esempio n. 1
0
    def __init__(self, path_rendered, dpkgRoot, dpkg,  **kwargs):
        Ccoder.__init__(self, dpkgRoot, dpkg, **kwargs)
        Data.__init__(self, path_rendered, dpkgRoot, dpkg,  **kwargs)

        self.path_rendered = os.path.abspath(unicode(path_rendered, 'utf8'))
        self.env = Environment(loader=FileSystemLoader(os.path.join(self.path_rendered, 'C', 'templates')))
        self.env.filters.update({
            'is_prior': lambda x: ('data' in x) and isinstance(x['data'], dict) and ('data' in x['data']) and ('distribution' in x['data']['data'])
        })
Esempio n. 2
0
File: Data.py Progetto: nvdnkpr/ssm
    def __init__(self, path_rendered, dpkgRoot, dpkg, **kwargs):
        Ccoder.__init__(self, dpkgRoot, dpkg, **kwargs)

        self.starts = [parse_date(x['start']) for x in self.obs_model]
        self.t0 =  min(self.starts)

        try:        
            #the .data.json contains all the data and metadata comming from the data package and it's dependencies'
            self._data = json.load(open(os.path.join(path_rendered,'.data.json')))
        except ValueError, IOError:
            raise DataError('could not process .data.json')
    def __init__(self, path_rendered, context, process, link):


        Context.__init__(self, context)
        Ccoder.__init__(self, context, process, link)

        self.path_rendered = path_rendered

        ##map_ts_obs
        self.map_ts_obs = {}
        for x in link['observed']:
            for ts in x['time_series_id']:
                self.map_ts_obs[ts] = x['id']


        ##########################
        ##sort context
        ##########################

        #tbs: to be sorted
        tbs = zip(self.ts_id, self._repeated_name_stream, self._repeated_name_ts)
        #sort by data_stream
        tbs.sort(key=lambda x: x[1])        
        #sort by name_ts (in python, sorts are guaranteed to be stable)
        tbs.sort(key=lambda x: x[2])
        #sort by obs_var (in python, sorts are guaranteed to be stable)
        tbs.sort(key=lambda x: self.obs_var.index(self.map_ts_obs[ x[0] ]))


        #we need to sort ts_id, _repeated_name_ts, _repeated_name_stream, _repeated_obs_type, data and all the par_fixed involved in the obs_model
        ind_sorted = [ self.ts_id.index(x[0]) for x in tbs ]

        self.ts_id = [ self.ts_id[x] for x in ind_sorted ]
        self._repeated_name_ts = [self._repeated_name_ts[x] for x in ind_sorted]
        self._repeated_name_stream = [self._repeated_name_stream[x] for x in ind_sorted]
        self._repeated_obs_type = [self._repeated_obs_type[x] for x in ind_sorted]

        #data
        if self.data:
            self.data = [ [ y[x] for x in ind_sorted ] for y in self.data ]
    def setUp(self):

        c = json.load(open(os.path.join('example', 'drift', 'context.json')))
        p = json.load(open(os.path.join('example', 'drift', 'process.json')))
        l = json.load(open(os.path.join('example', 'drift', 'link.json')))


        self.m_drift = Ccoder(c, p, l)

        c = json.load(open(os.path.join('example', 'noise', 'context.json')))
        p = json.load(open(os.path.join('example', 'noise', 'process.json')))
        l = json.load(open(os.path.join('example', 'noise', 'link.json')))

        self.m_noise = Ccoder(c, p, l)

        p = json.load(open(os.path.join('example', 'noise', 'process.json')))
        p["white_noise"][0]["reaction"][0] = {'to':'S','from':'U'}
        self.m_noise2 = Ccoder(c, p, l)


        p = json.load(open(os.path.join('example', 'noise', 'process.json')))
        p["white_noise"][0]["reaction"][0] = {'to':'R','from':'I'}
        self.m_noise3 = Ccoder(c, p, l)

        p = json.load(open(os.path.join('example', 'noise', 'process.json')))
        p["white_noise"][0]["reaction"][0] = {'to':'U','from':'I'}
        self.m_noise4 = Ccoder(c, p, l)

        p = json.load(open(os.path.join('example', 'noise', 'process.json')))
        p["model"].append({"from": "R", "to": "U",  "rate": "mu_d", "comment":"death"})
        p["white_noise"][0]["reaction"][0] = {'to':'U','from':'R'}
        self.m_noise5 = Ccoder(c, p, l)

        p = json.load(open(os.path.join('example', 'noise', 'process.json')))
        p["white_noise"][0]["reaction"].append({'to':'R','from':'I'})
        self.m_noise6 = Ccoder(c, p, l)

        p = json.load(open(os.path.join('example', 'noise', 'process.json')))
        p["white_noise"].append({"reaction":[{'to':'R','from':'I'}],"sd":"sto"})
        self.m_noise7 = Ccoder(c, p, l)

        p = json.load(open(os.path.join('example', 'drift', 'process.json')))
        p["model"].append({"from": "R", "to": "I", "rate": "correct_rate(v)", "comment":"testing"}) 
        self.m_drift2 = Ccoder(c, p, l)
Esempio n. 5
0
    def setUp(self):
        dpkgRoot = os.path.join('..' ,'examples', 'noise')
        dpkg = json.load(open(os.path.join(dpkgRoot, 'ssm.json')))
        
        self.m_noise = Ccoder(dpkgRoot, copy.deepcopy(dpkg))
        
        m_diff = copy.deepcopy(dpkg)    
        del m_diff['reactions'][2]['white_noise']
        del m_diff['reactions'][3]['white_noise']
        m_diff['sde'] = {
            'drift': [
                {'name': 'r0_paris', 'f': 0.0, 'transformation': 'log(r0_paris)'},
                {'name': 'r0_nyc', 'f': 0.0, 'transformation': 'log(r0_nyc)'}
            ],
            'dispertion': [['vol',0],[0,'vol']]
        }
        self.m_diff = Ccoder(dpkgRoot, m_diff)

        m_noise2 = copy.deepcopy(dpkg)    
        del m_noise2['reactions'][2]['white_noise']
        del m_noise2['reactions'][3]['white_noise']
        m_noise2['reactions'][0]['white_noise'] = {'name':'noise_SI', 'sd': 'sto'}
        m_noise2['reactions'][1]['white_noise'] = {'name':'noise_SI2', 'sd': 'sto'}
        self.m_noise2 = Ccoder(dpkgRoot, m_noise2)

        m_noise3 = copy.deepcopy(dpkg)    
        del m_noise3['reactions'][2]['white_noise']
        del m_noise3['reactions'][3]['white_noise']
        m_noise3['reactions'][4]['white_noise'] = {'name':'noise_SI', 'sd': 'sto'}
        m_noise3['reactions'][5]['white_noise'] = {'name':'noise_SI2', 'sd': 'sto'}
        self.m_noise3 = Ccoder(dpkgRoot, m_noise3)

        m_noise4 = copy.deepcopy(dpkg)    
        del m_noise4['reactions'][2]['white_noise']
        del m_noise4['reactions'][3]['white_noise']
        m_noise4['reactions'][8]['white_noise'] = {'name':'noise_SI', 'sd': 'sto'}
        m_noise4['reactions'][9]['white_noise'] = {'name':'noise_SI2', 'sd': 'sto'}
        self.m_noise4 = Ccoder(dpkgRoot, m_noise4)

        m_noise5 = copy.deepcopy(dpkg)    
        del m_noise5['reactions'][2]['white_noise']
        del m_noise5['reactions'][3]['white_noise']
        m_noise5['reactions'][10]['white_noise'] = {'name':'noise_SI', 'sd': 'sto'}
        m_noise5['reactions'][11]['white_noise'] = {'name':'noise_SI2', 'sd': 'sto'}
        self.m_noise5 = Ccoder(dpkgRoot, m_noise5)

        m_noise6 = copy.deepcopy(dpkg)    
        m_noise6['reactions'][4]['white_noise'] = {'name':'noise_SI', 'sd': 'sto'}
        m_noise6['reactions'][5]['white_noise'] = {'name':'noise_SI2', 'sd': 'sto'}
        self.m_noise6 = Ccoder(dpkgRoot, m_noise6)

        m_noise7 = copy.deepcopy(dpkg)    
        m_noise7['reactions'][4]['white_noise'] = {'name':'noise_SI23', 'sd': 'sto'}
        m_noise7['reactions'][5]['white_noise'] = {'name':'noise_SI24', 'sd': 'sto'}
        self.m_noise7 = Ccoder(dpkgRoot, m_noise7)

        m_diff2 = copy.deepcopy(dpkg)    
        del m_diff2['reactions'][2]['white_noise']
        del m_diff2['reactions'][3]['white_noise']
        m_diff2['sde'] = copy.deepcopy(m_diff['sde'])
        m_diff2['reactions'].append({'from': 'R_paris', 'to': 'I_paris', 'rate': 'correct_rate(v)', 'description':'testing'})
        m_diff2['reactions'].append({'from': 'R_nyc', 'to': 'I_nyc', 'rate': 'correct_rate(v)', 'description':'testing'})
        self.m_diff2 = Ccoder(dpkgRoot, m_diff2)
Esempio n. 6
0
class TestCcoder(unittest.TestCase):

    def setUp(self):
        dpkgRoot = os.path.join('..' ,'examples', 'noise')
        dpkg = json.load(open(os.path.join(dpkgRoot, 'ssm.json')))
        
        self.m_noise = Ccoder(dpkgRoot, copy.deepcopy(dpkg))
        
        m_diff = copy.deepcopy(dpkg)    
        del m_diff['reactions'][2]['white_noise']
        del m_diff['reactions'][3]['white_noise']
        m_diff['sde'] = {
            'drift': [
                {'name': 'r0_paris', 'f': 0.0, 'transformation': 'log(r0_paris)'},
                {'name': 'r0_nyc', 'f': 0.0, 'transformation': 'log(r0_nyc)'}
            ],
            'dispertion': [['vol',0],[0,'vol']]
        }
        self.m_diff = Ccoder(dpkgRoot, m_diff)

        m_noise2 = copy.deepcopy(dpkg)    
        del m_noise2['reactions'][2]['white_noise']
        del m_noise2['reactions'][3]['white_noise']
        m_noise2['reactions'][0]['white_noise'] = {'name':'noise_SI', 'sd': 'sto'}
        m_noise2['reactions'][1]['white_noise'] = {'name':'noise_SI2', 'sd': 'sto'}
        self.m_noise2 = Ccoder(dpkgRoot, m_noise2)

        m_noise3 = copy.deepcopy(dpkg)    
        del m_noise3['reactions'][2]['white_noise']
        del m_noise3['reactions'][3]['white_noise']
        m_noise3['reactions'][4]['white_noise'] = {'name':'noise_SI', 'sd': 'sto'}
        m_noise3['reactions'][5]['white_noise'] = {'name':'noise_SI2', 'sd': 'sto'}
        self.m_noise3 = Ccoder(dpkgRoot, m_noise3)

        m_noise4 = copy.deepcopy(dpkg)    
        del m_noise4['reactions'][2]['white_noise']
        del m_noise4['reactions'][3]['white_noise']
        m_noise4['reactions'][8]['white_noise'] = {'name':'noise_SI', 'sd': 'sto'}
        m_noise4['reactions'][9]['white_noise'] = {'name':'noise_SI2', 'sd': 'sto'}
        self.m_noise4 = Ccoder(dpkgRoot, m_noise4)

        m_noise5 = copy.deepcopy(dpkg)    
        del m_noise5['reactions'][2]['white_noise']
        del m_noise5['reactions'][3]['white_noise']
        m_noise5['reactions'][10]['white_noise'] = {'name':'noise_SI', 'sd': 'sto'}
        m_noise5['reactions'][11]['white_noise'] = {'name':'noise_SI2', 'sd': 'sto'}
        self.m_noise5 = Ccoder(dpkgRoot, m_noise5)

        m_noise6 = copy.deepcopy(dpkg)    
        m_noise6['reactions'][4]['white_noise'] = {'name':'noise_SI', 'sd': 'sto'}
        m_noise6['reactions'][5]['white_noise'] = {'name':'noise_SI2', 'sd': 'sto'}
        self.m_noise6 = Ccoder(dpkgRoot, m_noise6)

        m_noise7 = copy.deepcopy(dpkg)    
        m_noise7['reactions'][4]['white_noise'] = {'name':'noise_SI23', 'sd': 'sto'}
        m_noise7['reactions'][5]['white_noise'] = {'name':'noise_SI24', 'sd': 'sto'}
        self.m_noise7 = Ccoder(dpkgRoot, m_noise7)

        m_diff2 = copy.deepcopy(dpkg)    
        del m_diff2['reactions'][2]['white_noise']
        del m_diff2['reactions'][3]['white_noise']
        m_diff2['sde'] = copy.deepcopy(m_diff['sde'])
        m_diff2['reactions'].append({'from': 'R_paris', 'to': 'I_paris', 'rate': 'correct_rate(v)', 'description':'testing'})
        m_diff2['reactions'].append({'from': 'R_nyc', 'to': 'I_nyc', 'rate': 'correct_rate(v)', 'description':'testing'})
        self.m_diff2 = Ccoder(dpkgRoot, m_diff2)
    

    def test_eval_Q(self):
        calc_Q = self.m_noise.eval_Q()

        # testing env sto only
        # order: I_nyc, I_paris, S_nyc, S_paris, inc_all , inc_nyc
        term_paris = '((((r0_paris/N_paris*v*I_paris)*S_paris)*((sto)**2))*((r0_paris/N_paris*v*I_paris)*S_paris)))'
        term_nyc = '((((r0_nyc/N_nyc*v*I_nyc)*S_nyc)*((sto)**2))*((r0_nyc/N_nyc*v*I_nyc)*S_nyc)))'
        Q_cm = calc_Q["no_dem_sto"]["Q_cm"]
        self.assertEqual(Q_cm[0][0], '((1)*'+term_nyc+'*(1)')
        self.assertEqual(Q_cm[0][1], 0)
        self.assertEqual(Q_cm[0][2], '((1)*'+term_nyc+'*(-1)')
        self.assertEqual(Q_cm[0][3], 0)
        self.assertEqual(Q_cm[0][4], 0)
        self.assertEqual(Q_cm[0][5], '((1)*'+term_nyc+'*(1)')
        self.assertEqual(Q_cm[1][0], 0)
        self.assertEqual(Q_cm[1][1], '((1)*'+term_paris+'*(1)')
        self.assertEqual(Q_cm[1][2], 0)
        self.assertEqual(Q_cm[1][3], '((1)*'+term_paris+'*(-1)')
        self.assertEqual(Q_cm[1][4], 0)
        self.assertEqual(Q_cm[1][5], 0)
        self.assertEqual(Q_cm[2][0], '((-1)*'+term_nyc+'*(1)')
        self.assertEqual(Q_cm[2][1], 0)
        self.assertEqual(Q_cm[2][2], '((-1)*'+term_nyc+'*(-1)')
        self.assertEqual(Q_cm[2][3], 0)
        self.assertEqual(Q_cm[2][4], 0)
        self.assertEqual(Q_cm[2][5], '((-1)*'+term_nyc+'*(1)')
        self.assertEqual(Q_cm[3][0], 0)
        self.assertEqual(Q_cm[3][1], '((-1)*'+term_paris+'*(1)')
        self.assertEqual(Q_cm[3][2], 0)
        self.assertEqual(Q_cm[3][3], '((-1)*'+term_paris+'*(-1)')
        self.assertEqual(Q_cm[3][4], 0)
        self.assertEqual(Q_cm[3][5], 0)
        self.assertEqual(Q_cm[4][0], 0)
        self.assertEqual(Q_cm[4][1], 0)
        self.assertEqual(Q_cm[4][2], 0)
        self.assertEqual(Q_cm[4][3], 0)
        self.assertEqual(Q_cm[4][4], 0)
        self.assertEqual(Q_cm[4][5], 0)
        self.assertEqual(Q_cm[5][0], '((1)*'+term_nyc+'*(1)')
        self.assertEqual(Q_cm[5][1], 0)
        self.assertEqual(Q_cm[5][2], '((1)*'+term_nyc+'*(-1)')
        self.assertEqual(Q_cm[5][3], 0)
        self.assertEqual(Q_cm[5][4], 0)
        self.assertEqual(Q_cm[5][5], '((1)*'+term_nyc+'*(1)')

        # testing dem sto only
        term1_p = '(mu_b_paris*N_paris))'
        term2_p = '((r0_paris/N_paris*v*I_paris)*S_paris))'
        term3_p = '((correct_rate(v))*I_paris))'
        term4_p = '((mu_d_paris)*S_paris))'
        term5_p = '((mu_d_paris)*I_paris))'
        term1_n = '(mu_b_nyc*N_nyc))'
        term2_n = '((r0_nyc/N_nyc*v*I_nyc)*S_nyc))'
        term3_n = '((correct_rate(v))*I_nyc))'
        term4_n = '((mu_d_nyc)*S_nyc))'
        term5_n = '((mu_d_nyc)*I_nyc))'
        # order: I_nyc, I_paris, S_nyc, S_paris, inc_all , inc_nyc
        Q_cm = calc_Q["no_env_sto"]["Q_cm"]
        self.assertEqual(Q_cm[0][0], '((1)*'+term2_n+'*(1) + ((-1)*'+term3_n+'*(-1) + ((-1)*'+term5_n+'*(-1)')
        self.assertEqual(Q_cm[0][1], 0)
        self.assertEqual(Q_cm[0][2], '((1)*'+term2_n+'*(-1)')
        self.assertEqual(Q_cm[0][3], 0)
        self.assertEqual(Q_cm[0][4], '((-1)*'+term3_n+'*(1) + ((-1)*'+term5_n+'*(1)')
        self.assertEqual(Q_cm[0][5], '((1)*'+term2_n+'*(1)')
        self.assertEqual(Q_cm[1][0], 0)
        self.assertEqual(Q_cm[1][1], '((1)*'+term2_p+'*(1) + ((-1)*'+term3_p+'*(-1) + ((-1)*'+term5_p+'*(-1)')
        self.assertEqual(Q_cm[1][2], 0)
        self.assertEqual(Q_cm[1][3], '((1)*'+term2_p+'*(-1)')
        self.assertEqual(Q_cm[1][4], '((-1)*'+term3_p+'*(1) + ((-1)*'+term5_p+'*(1)')
        self.assertEqual(Q_cm[1][5], 0)
        self.assertEqual(Q_cm[2][0], '((-1)*'+term2_n+'*(1)')
        self.assertEqual(Q_cm[2][1], 0)
        self.assertEqual(Q_cm[2][2], '((1)*'+term1_n+'*(1) + ((-1)*'+term2_n+'*(-1) + ((-1)*'+term4_n+'*(-1)')
        self.assertEqual(Q_cm[2][3], 0)
        self.assertEqual(Q_cm[2][4], 0)
        self.assertEqual(Q_cm[2][5], '((-1)*'+term2_n+'*(1)')
        self.assertEqual(Q_cm[3][0], 0)
        self.assertEqual(Q_cm[3][1], '((-1)*'+term2_p+'*(1)')
        self.assertEqual(Q_cm[3][2], 0)
        self.assertEqual(Q_cm[3][3], '((1)*'+term1_p+'*(1) + ((-1)*'+term2_p+'*(-1) + ((-1)*'+term4_p+'*(-1)')
        self.assertEqual(Q_cm[3][4], 0)
        self.assertEqual(Q_cm[3][5], 0)
        self.assertEqual(Q_cm[4][0], '((1)*'+term3_n+'*(-1) + ((1)*'+term5_n+'*(-1)')
        self.assertEqual(Q_cm[4][1], '((1)*'+term3_p+'*(-1) + ((1)*'+term5_p+'*(-1)')
        self.assertEqual(Q_cm[4][2], 0)
        self.assertEqual(Q_cm[4][3], 0)
        self.assertEqual(Q_cm[4][4], '((1)*'+term3_p+'*(1) + ((1)*'+term3_n+'*(1) + ((1)*'+term5_p+'*(1) + ((1)*'+term5_n+'*(1)')
        self.assertEqual(Q_cm[4][5], 0)
        self.assertEqual(Q_cm[5][0], '((1)*'+term2_n+'*(1)')
        self.assertEqual(Q_cm[5][1], 0)
        self.assertEqual(Q_cm[5][2], '((1)*'+term2_n+'*(-1)')
        self.assertEqual(Q_cm[5][3], 0)
        self.assertEqual(Q_cm[5][4], 0)
        self.assertEqual(Q_cm[5][5], '((1)*'+term2_n+'*(1)')
        

    def test_eval_Q_tricky_cases(self):

        calc_Q = self.m_noise2.eval_Q()
        # testing env sto only for m_noise2 : WN on U->S
        term_p = '(((mu_b_paris*N_paris)*((sto)**2))*(mu_b_paris*N_paris)))'
        term_n = '(((mu_b_nyc*N_nyc)*((sto)**2))*(mu_b_nyc*N_nyc)))'
        for i in range(5):
            for j in range(5):
                if i==2 and j == 2:
                    self.assertEqual(calc_Q["no_dem_sto"]["Q_cm"][i][j],'((1)*'+term_n+'*(1)')
                elif i==3 and j == 3:
                    self.assertEqual(calc_Q["no_dem_sto"]["Q_cm"][i][j],'((1)*'+term_p+'*(1)')
                else:
                    self.assertEqual(calc_Q["no_dem_sto"]["Q_cm"][i][j],0)


        calc_Q = self.m_noise3.eval_Q()
        # testing env sto only for m_noise3 : WN on I->R
        term_p = '((((correct_rate(v))*I_paris)*((sto)**2))*((correct_rate(v))*I_paris)))'
        term_n = '((((correct_rate(v))*I_nyc)*((sto)**2))*((correct_rate(v))*I_nyc)))'
        Q_cm = calc_Q["no_dem_sto"]["Q_cm"]
        for i in range(5):
            for j in range(5):
                if i==0 and j == 0:
                    self.assertEqual(Q_cm[i][j], '((-1)*'+term_n+'*(-1)')
                elif i==1 and j == 1:
                    self.assertEqual(Q_cm[i][j], '((-1)*'+term_p+'*(-1)')
                elif i==0  and j == 4:
                    self.assertEqual(Q_cm[i][j], '((-1)*'+term_n+'*(1)')
                elif i==4  and j == 0:
                    self.assertEqual(Q_cm[i][j], '((1)*'+term_n+'*(-1)')
                elif i==1  and j == 4:
                    self.assertEqual(Q_cm[i][j], '((-1)*'+term_p+'*(1)')
                elif i==4  and j == 1:
                    self.assertEqual(Q_cm[i][j], '((1)*'+term_p+'*(-1)')
                elif i==4  and j == 4:
                    self.assertEqual(Q_cm[i][j], '((1)*'+term_p+'*(1) + ((1)*'+term_n+'*(1)')
                else:
                    self.assertEqual(Q_cm[i][j], 0)
        

        calc_Q = self.m_noise4.eval_Q()
        # testing env sto only for m_noise4 : WN on I->U
        term_p = '((((mu_d_paris)*I_paris)*((sto)**2))*((mu_d_paris)*I_paris)))'
        term_n = '((((mu_d_nyc)*I_nyc)*((sto)**2))*((mu_d_nyc)*I_nyc)))'
        Q_cm = calc_Q["no_dem_sto"]["Q_cm"]
        for i in range(5):
            for j in range(5):
                if i==0 and j == 0:
                    self.assertEqual(Q_cm[i][j], '((-1)*'+term_n+'*(-1)')
                elif i==1 and j == 1:
                    self.assertEqual(Q_cm[i][j], '((-1)*'+term_p+'*(-1)')
                elif i==1  and j == 4:
                    self.assertEqual(Q_cm[i][j], '((-1)*'+term_p+'*(1)')
                elif i==4  and j == 1:
                    self.assertEqual(Q_cm[i][j], '((1)*'+term_p+'*(-1)')
                elif i==0  and j == 4:
                    self.assertEqual(Q_cm[i][j], '((-1)*'+term_n+'*(1)')
                elif i==4  and j == 0:
                    self.assertEqual(Q_cm[i][j], '((1)*'+term_n+'*(-1)')
                elif i==4  and j == 4:
                    self.assertEqual(Q_cm[i][j], '((1)*'+term_p+'*(1) + ((1)*'+term_n+'*(1)')
                else:
                    self.assertEqual(Q_cm[i][j], 0)

                    

        calc_Q = self.m_noise5.eval_Q()
        # testing env sto only for m_noise5 : WN on R->U
        for i in range(5):
            for j in range(5):
                self.assertEqual(calc_Q["no_dem_sto"]["Q_cm"][i][j],0)

        calc_Q = self.m_noise6.eval_Q()
        # testing env sto only for m_noise6 : correlated WN on I->R and S->I
        term1_p = '((r0_paris/N_paris*v*I_paris)*S_paris)'
        term2_p = '((correct_rate(v))*I_paris)'
        term1_n = '((r0_nyc/N_nyc*v*I_nyc)*S_nyc)'
        term2_n = '((correct_rate(v))*I_nyc)'
        Q_cm = calc_Q["no_dem_sto"]["Q_cm"]
        self.assertEqual(Q_cm[0][0], '((1)*(('+term1_n+'*((sto)**2))*'+term1_n+') + (-1)*(('+term2_n+'*((sto)**2))*'+term1_n+'))*(1) + ((1)*(('+term1_n+'*((sto)**2))*'+term2_n+') + (-1)*(('+term2_n+'*((sto)**2))*'+term2_n+'))*(-1)')
        self.assertEqual(Q_cm[0][1], 0)
        self.assertEqual(Q_cm[0][2], '((1)*(('+term1_n+'*((sto)**2))*'+term1_n+') + (-1)*(('+term2_n+'*((sto)**2))*'+term1_n+'))*(-1)')
        self.assertEqual(Q_cm[0][3], 0)
        self.assertEqual(Q_cm[0][4], '((1)*(('+term1_n+'*((sto)**2))*'+term2_n+') + (-1)*(('+term2_n+'*((sto)**2))*'+term2_n+'))*(1)')
        self.assertEqual(Q_cm[0][5], '((1)*(('+term1_n+'*((sto)**2))*'+term1_n+') + (-1)*(('+term2_n+'*((sto)**2))*'+term1_n+'))*(1)')
        self.assertEqual(Q_cm[1][0], 0)
        self.assertEqual(Q_cm[1][1], '((1)*(('+term1_p+'*((sto)**2))*'+term1_p+') + (-1)*(('+term2_p+'*((sto)**2))*'+term1_p+'))*(1) + ((1)*(('+term1_p+'*((sto)**2))*'+term2_p+') + (-1)*(('+term2_p+'*((sto)**2))*'+term2_p+'))*(-1)')
        self.assertEqual(Q_cm[1][2], 0)
        self.assertEqual(Q_cm[1][3], '((1)*(('+term1_p+'*((sto)**2))*'+term1_p+') + (-1)*(('+term2_p+'*((sto)**2))*'+term1_p+'))*(-1)')
        self.assertEqual(Q_cm[1][4], '((1)*(('+term1_p+'*((sto)**2))*'+term2_p+') + (-1)*(('+term2_p+'*((sto)**2))*'+term2_p+'))*(1)')
        self.assertEqual(Q_cm[1][5], 0)
        self.assertEqual(Q_cm[2][0], '((-1)*(('+term1_n+'*((sto)**2))*'+term1_n+'))*(1) + ((-1)*(('+term1_n+'*((sto)**2))*'+term2_n+'))*(-1)')
        self.assertEqual(Q_cm[2][1], 0)
        self.assertEqual(Q_cm[2][2], '((-1)*(('+term1_n+'*((sto)**2))*'+term1_n+'))*(-1)')
        self.assertEqual(Q_cm[2][3], 0)
        self.assertEqual(Q_cm[2][4], '((-1)*(('+term1_n+'*((sto)**2))*'+term2_n+'))*(1)')
        self.assertEqual(Q_cm[2][5], '((-1)*(('+term1_n+'*((sto)**2))*'+term1_n+'))*(1)')
        self.assertEqual(Q_cm[3][0], 0)
        self.assertEqual(Q_cm[3][1], '((-1)*(('+term1_p+'*((sto)**2))*'+term1_p+'))*(1) + ((-1)*(('+term1_p+'*((sto)**2))*'+term2_p+'))*(-1)')
        self.assertEqual(Q_cm[3][2], 0)
        self.assertEqual(Q_cm[3][3], '((-1)*(('+term1_p+'*((sto)**2))*'+term1_p+'))*(-1)')
        
        self.assertEqual(Q_cm[3][4], '((-1)*(('+term1_p+'*((sto)**2))*'+term2_p+'))*(1)')
        self.assertEqual(Q_cm[3][5], 0)
        self.assertEqual(Q_cm[4][0], '((1)*(('+term2_n+'*((sto)**2))*'+term1_n+'))*(1) + ((1)*(('+term2_n+'*((sto)**2))*'+term2_n+'))*(-1)')
        self.assertEqual(Q_cm[4][1], '((1)*(('+term2_p+'*((sto)**2))*'+term1_p+'))*(1) + ((1)*(('+term2_p+'*((sto)**2))*'+term2_p+'))*(-1)')
        self.assertEqual(Q_cm[4][2], '((1)*(('+term2_n+'*((sto)**2))*'+term1_n+'))*(-1)')
        self.assertEqual(Q_cm[4][3], '((1)*(('+term2_p+'*((sto)**2))*'+term1_p+'))*(-1)')
        self.assertEqual(Q_cm[4][4], '((1)*(('+term2_p+'*((sto)**2))*'+term2_p+'))*(1) + ((1)*(('+term2_n+'*((sto)**2))*'+term2_n+'))*(1)')
        self.assertEqual(Q_cm[4][5], '((1)*(('+term2_n+'*((sto)**2))*'+term1_n+'))*(1)')
        self.assertEqual(Q_cm[5][0], '((1)*(('+term1_n+'*((sto)**2))*'+term1_n+'))*(1) + ((1)*(('+term1_n+'*((sto)**2))*'+term2_n+'))*(-1)')
        self.assertEqual(Q_cm[5][1], 0)
        self.assertEqual(Q_cm[5][2], '((1)*(('+term1_n+'*((sto)**2))*'+term1_n+'))*(-1)')
        self.assertEqual(Q_cm[5][3], 0)
        self.assertEqual(Q_cm[5][4], '((1)*(('+term1_n+'*((sto)**2))*'+term2_n+'))*(1)')
        self.assertEqual(Q_cm[5][5], '((1)*(('+term1_n+'*((sto)**2))*'+term1_n+'))*(1)')
        
        calc_Q = self.m_noise7.eval_Q()
        # testing env sto only for m_noise7 : uncorrelated WN on I->R and S->I
        term1_p = '((r0_paris/N_paris*v*I_paris)*S_paris)'
        term2_p = '((correct_rate(v))*I_paris)'
        term1_n = '((r0_nyc/N_nyc*v*I_nyc)*S_nyc)'
        term2_n = '((correct_rate(v))*I_nyc)'
        Q_cm = calc_Q["no_dem_sto"]["Q_cm"]
        self.assertEqual(Q_cm[0][0], '((1)*(('+term1_n+'*((sto)**2))*'+term1_n+'))*(1) + ((-1)*(('+term2_n+'*((sto)**2))*'+term2_n+'))*(-1)')
        self.assertEqual(Q_cm[0][1], 0)
        self.assertEqual(Q_cm[0][2], '((1)*(('+term1_n+'*((sto)**2))*'+term1_n+'))*(-1)')
        self.assertEqual(Q_cm[0][3], 0)
        self.assertEqual(Q_cm[0][4], '((-1)*(('+term2_n+'*((sto)**2))*'+term2_n+'))*(1)')
        self.assertEqual(Q_cm[0][5], '((1)*(('+term1_n+'*((sto)**2))*'+term1_n+'))*(1)')
        self.assertEqual(Q_cm[1][0], 0)
        self.assertEqual(Q_cm[1][1], '((1)*(('+term1_p+'*((sto)**2))*'+term1_p+'))*(1) + ((-1)*(('+term2_p+'*((sto)**2))*'+term2_p+'))*(-1)')
        self.assertEqual(Q_cm[1][2], 0)
        self.assertEqual(Q_cm[1][3], '((1)*(('+term1_p+'*((sto)**2))*'+term1_p+'))*(-1)')
        self.assertEqual(Q_cm[1][4], '((-1)*(('+term2_p+'*((sto)**2))*'+term2_p+'))*(1)')
        self.assertEqual(Q_cm[1][5], 0)
        self.assertEqual(Q_cm[2][0], '((-1)*(('+term1_n+'*((sto)**2))*'+term1_n+'))*(1)')
        self.assertEqual(Q_cm[2][1], 0)
        self.assertEqual(Q_cm[2][2], '((-1)*(('+term1_n+'*((sto)**2))*'+term1_n+'))*(-1)')
        self.assertEqual(Q_cm[2][3], 0)
        self.assertEqual(Q_cm[2][4], 0)
        self.assertEqual(Q_cm[2][5], '((-1)*(('+term1_n+'*((sto)**2))*'+term1_n+'))*(1)')
        self.assertEqual(Q_cm[3][0], 0)
        self.assertEqual(Q_cm[3][1], '((-1)*(('+term1_p+'*((sto)**2))*'+term1_p+'))*(1)')
        self.assertEqual(Q_cm[3][2], 0)
        self.assertEqual(Q_cm[3][3], '((-1)*(('+term1_p+'*((sto)**2))*'+term1_p+'))*(-1)')
        
        self.assertEqual(Q_cm[3][4], 0)
        self.assertEqual(Q_cm[3][5], 0)
        self.assertEqual(Q_cm[4][0], '((1)*(('+term2_n+'*((sto)**2))*'+term2_n+'))*(-1)')
        self.assertEqual(Q_cm[4][1], '((1)*(('+term2_p+'*((sto)**2))*'+term2_p+'))*(-1)')
        self.assertEqual(Q_cm[4][2], 0)
        self.assertEqual(Q_cm[4][3], 0)
        self.assertEqual(Q_cm[4][4], '((1)*(('+term2_p+'*((sto)**2))*'+term2_p+'))*(1) + ((1)*(('+term2_n+'*((sto)**2))*'+term2_n+'))*(1)')
        self.assertEqual(Q_cm[4][5], 0)
        self.assertEqual(Q_cm[5][0], '((1)*(('+term1_n+'*((sto)**2))*'+term1_n+'))*(1)')
        self.assertEqual(Q_cm[5][1], 0)
        self.assertEqual(Q_cm[5][2], '((1)*(('+term1_n+'*((sto)**2))*'+term1_n+'))*(-1)')
        self.assertEqual(Q_cm[5][3], 0)
        self.assertEqual(Q_cm[5][4], 0)
        self.assertEqual(Q_cm[5][5], '((1)*(('+term1_n+'*((sto)**2))*'+term1_n+'))*(1)')

    def test_jac(self):
        step_ode_sde = self.m_noise.step_ode_sde()
        jac = self.m_diff.jac(step_ode_sde['sf'])

        # testing jac
        # I ode - ((v)*I) - ((mu_d)*I) + ((r0/N*v*I)*S)
        self.assertEqual(jac['caches'][jac['jac'][0][0]], '-gsl_spline_eval(calc->spline[ORDER_mu_d_nyc],t,calc->acc[ORDER_mu_d_nyc])-(gsl_vector_get(par,ORDER_v))+X[ORDER_S_nyc]*diffed[ORDER_diff__r0_nyc]*gsl_vector_get(par,ORDER_v)/gsl_spline_eval(calc->spline[ORDER_N_nyc],t,calc->acc[ORDER_N_nyc])')
        self.assertEqual(jac['caches'][jac['jac'][1][1]], '-gsl_spline_eval(calc->spline[ORDER_mu_d_paris],t,calc->acc[ORDER_mu_d_paris])-(gsl_vector_get(par,ORDER_v))+X[ORDER_S_paris]*diffed[ORDER_diff__r0_paris]*gsl_vector_get(par,ORDER_v)/gsl_spline_eval(calc->spline[ORDER_N_paris],t,calc->acc[ORDER_N_paris])')
        self.assertEqual(jac['caches'][jac['jac_diff'][1][0]['value']], '0')
        self.assertEqual(jac['caches'][jac['jac_diff'][0][1]['value']], '0')
        
        # S ode - ((r0/N*v*I)*S) - ((mu_d)*S) + (mu_b*N)
        self.assertEqual(jac['caches'][jac['jac'][2][2]], '-X[ORDER_I_nyc]*diffed[ORDER_diff__r0_nyc]*gsl_vector_get(par,ORDER_v)/gsl_spline_eval(calc->spline[ORDER_N_nyc],t,calc->acc[ORDER_N_nyc])-gsl_spline_eval(calc->spline[ORDER_mu_d_nyc],t,calc->acc[ORDER_mu_d_nyc])')
        self.assertEqual(jac['caches'][jac['jac'][3][3]], '-X[ORDER_I_paris]*diffed[ORDER_diff__r0_paris]*gsl_vector_get(par,ORDER_v)/gsl_spline_eval(calc->spline[ORDER_N_paris],t,calc->acc[ORDER_N_paris])-gsl_spline_eval(calc->spline[ORDER_mu_d_paris],t,calc->acc[ORDER_mu_d_paris])')
        self.assertEqual(jac['caches'][jac['jac'][2][0]], '-X[ORDER_S_nyc]*diffed[ORDER_diff__r0_nyc]*gsl_vector_get(par,ORDER_v)/gsl_spline_eval(calc->spline[ORDER_N_nyc],t,calc->acc[ORDER_N_nyc])')
        self.assertEqual(jac['caches'][jac['jac'][3][1]], '-X[ORDER_S_paris]*diffed[ORDER_diff__r0_paris]*gsl_vector_get(par,ORDER_v)/gsl_spline_eval(calc->spline[ORDER_N_paris],t,calc->acc[ORDER_N_paris])')
        
        
        # testing jac_obs
        # all_inc
        self.assertEqual(jac['caches'][jac['jac_obs'][0][0]], 'gsl_spline_eval(calc->spline[ORDER_mu_d_nyc],t,calc->acc[ORDER_mu_d_nyc])+(gsl_vector_get(par,ORDER_v))')
        self.assertEqual(jac['caches'][jac['jac_obs'][0][1]], 'gsl_spline_eval(calc->spline[ORDER_mu_d_paris],t,calc->acc[ORDER_mu_d_paris])+(gsl_vector_get(par,ORDER_v))')
        self.assertEqual(jac['caches'][jac['jac_obs_diff'][0][0]['value']], '0')
        self.assertEqual(jac['caches'][jac['jac_obs_diff'][0][1]['value']], '0')
        # nyc_inc
        self.assertEqual(jac['caches'][jac['jac_obs'][1][0]], 'X[ORDER_S_nyc]*diffed[ORDER_diff__r0_nyc]*gsl_vector_get(par,ORDER_v)/gsl_spline_eval(calc->spline[ORDER_N_nyc],t,calc->acc[ORDER_N_nyc])')
        self.assertEqual(jac['caches'][jac['jac_obs'][1][1]], '0')
        self.assertEqual(jac['caches'][jac['jac_obs_diff'][1][0]['value']], 'X[ORDER_I_nyc]*X[ORDER_S_nyc]*gsl_vector_get(par,ORDER_v)/gsl_spline_eval(calc->spline[ORDER_N_nyc],t,calc->acc[ORDER_N_nyc])')
        self.assertEqual(jac['caches'][jac['jac_obs_diff'][1][1]['value']], '0')
        

    def test_cache_special_function_C(self):

        caches = map(lambda x: self.m_diff.make_C_term(x, False), ['sin(2*PI*(t +r0))', 'sin(2*PI*(t +r0))', 'sin(2*PI*(t +r0)) + correct_rate(v)'])
        sf = self.m_diff.cache_special_function_C(caches)

        self.assertEqual(sf, ['sin(2*PI*(r0+t))', 'ssm_correct_rate(gsl_vector_get(par,ORDER_v),dt)'])
        self.assertEqual(caches, ['_sf[0]', '_sf[0]', '_sf[1]+_sf[0]'])


    def test_cache_special_function_C_nested(self):

        caches = map(lambda x: self.m_diff.make_C_term(x, False), ['pow(correct_rate(correct_rate(v)), pow(2,4))'])
        sf = self.m_diff.cache_special_function_C(caches)

        self.assertEqual(sf, ['pow(ssm_correct_rate(ssm_correct_rate(gsl_vector_get(par,ORDER_v),dt),dt),pow(2,4))'])
        self.assertEqual(caches, ['_sf[0]'])
class TestCcoder(unittest.TestCase):

    def setUp(self):

        c = json.load(open(os.path.join('example', 'drift', 'context.json')))
        p = json.load(open(os.path.join('example', 'drift', 'process.json')))
        l = json.load(open(os.path.join('example', 'drift', 'link.json')))


        self.m_drift = Ccoder(c, p, l)

        c = json.load(open(os.path.join('example', 'noise', 'context.json')))
        p = json.load(open(os.path.join('example', 'noise', 'process.json')))
        l = json.load(open(os.path.join('example', 'noise', 'link.json')))

        self.m_noise = Ccoder(c, p, l)

        p = json.load(open(os.path.join('example', 'noise', 'process.json')))
        p["white_noise"][0]["reaction"][0] = {'to':'S','from':'U'}
        self.m_noise2 = Ccoder(c, p, l)


        p = json.load(open(os.path.join('example', 'noise', 'process.json')))
        p["white_noise"][0]["reaction"][0] = {'to':'R','from':'I'}
        self.m_noise3 = Ccoder(c, p, l)

        p = json.load(open(os.path.join('example', 'noise', 'process.json')))
        p["white_noise"][0]["reaction"][0] = {'to':'U','from':'I'}
        self.m_noise4 = Ccoder(c, p, l)

        p = json.load(open(os.path.join('example', 'noise', 'process.json')))
        p["model"].append({"from": "R", "to": "U",  "rate": "mu_d", "comment":"death"})
        p["white_noise"][0]["reaction"][0] = {'to':'U','from':'R'}
        self.m_noise5 = Ccoder(c, p, l)

        p = json.load(open(os.path.join('example', 'noise', 'process.json')))
        p["white_noise"][0]["reaction"].append({'to':'R','from':'I'})
        self.m_noise6 = Ccoder(c, p, l)

        p = json.load(open(os.path.join('example', 'noise', 'process.json')))
        p["white_noise"].append({"reaction":[{'to':'R','from':'I'}],"sd":"sto"})
        self.m_noise7 = Ccoder(c, p, l)

        p = json.load(open(os.path.join('example', 'drift', 'process.json')))
        p["model"].append({"from": "R", "to": "I", "rate": "correct_rate(v)", "comment":"testing"}) 
        self.m_drift2 = Ccoder(c, p, l)



    def test_make_C_term(self):
        terms = [
            {'x': 'mu_b*(1.0+v*sin((v/N+(mu_b)))) + r0', #input
             'h': 'mu_b*(v*sin(mu_b + v/N) + 1.0) + r0', #expected human output
             'c': 'gsl_spline_eval(p_calc->spline[ORDER_mu_b][cac],t,p_calc->acc[ORDER_mu_b][cac])*(par[ORDER_v][routers[ORDER_v]->map[cac]]*sin(gsl_spline_eval(p_calc->spline[ORDER_mu_b][cac],t,p_calc->acc[ORDER_mu_b][cac])+par[ORDER_v][routers[ORDER_v]->map[cac]]/gsl_spline_eval(p_calc->spline[ORDER_N][cac],t,p_calc->acc[ORDER_N][cac]))+1.0)+drifted[ORDER_drift__par_proc__r0][cac]'}, #expected C output

            {'x': 'N-S-I+S+I',
             'h': 'N',
             'c': 'gsl_spline_eval(p_calc->spline[ORDER_N][cac],t,p_calc->acc[ORDER_N][cac])'},

            {'x': 'rep*(1.0-rep)*prop*x + (rep*phi*prop*x)**2',
             'h': 'pow(phi, 2)*pow(rep, 2)*pow(x, 2)*pow(prop, 2) + rep*x*prop*(-rep + 1.0)',
             'c': 'pow(par[ORDER_phi][routers[ORDER_phi]->map[ts]],2)*pow(par[ORDER_rep][routers[ORDER_rep]->map[ts]],2)*pow(x,2)*pow(gsl_spline_eval(p_calc->spline[ORDER_prop][ts],t,p_calc->acc[ORDER_prop][ts]),2)+par[ORDER_rep][routers[ORDER_rep]->map[ts]]*x*gsl_spline_eval(p_calc->spline[ORDER_prop][ts],t,p_calc->acc[ORDER_prop][ts])*(-par[ORDER_rep][routers[ORDER_rep]->map[ts]]+1.0)'},
        ]
            
        for t in terms:
            self.assertEqual(self.m_drift.make_C_term(t['x'], False, human=True), t['h'])
            self.assertEqual(self.m_drift.make_C_term(t['x'], False, human=False), t['c'])


    def test_make_C_term_derivate(self):
        x = 'sin(2*M_PI*(t/ONE_YEAR +r0))'
        h = '2*M_PI*cos(2*M_PI*(r0 + t/ONE_YEAR))'
        c = '2*M_PI*cos(2*M_PI*(drifted[ORDER_drift__par_proc__r0][cac]+t/ONE_YEAR))'

        self.assertEqual(self.m_drift.make_C_term(x, False, human=True, derivate='r0'), h)
        self.assertEqual(self.m_drift.make_C_term(x, False, human=False, derivate='r0'), c)


    def test_make_C_term_skip_correct_rate(self):
        #correct_rate is only skipped for C code

        x = 'mu_b*(1.0+correct_rate(v)*sin((correct_rate(v)/N+(mu_b)))) + r0'
        c = 'gsl_spline_eval(p_calc->spline[ORDER_mu_b][cac],t,p_calc->acc[ORDER_mu_b][cac])*((par[ORDER_v][routers[ORDER_v]->map[cac]])*sin(gsl_spline_eval(p_calc->spline[ORDER_mu_b][cac],t,p_calc->acc[ORDER_mu_b][cac])+(par[ORDER_v][routers[ORDER_v]->map[cac]])/gsl_spline_eval(p_calc->spline[ORDER_N][cac],t,p_calc->acc[ORDER_N][cac]))+1.0)+drifted[ORDER_drift__par_proc__r0][cac]'

        self.assertEqual(self.m_drift.make_C_term(x, True, human=False), c)


    def test_make_C_term_extra_terms(self):
        terms = [
            {'x': 'terms_forcing(v)', 
             'c': 'terms_forcing(par[ORDER_v][routers[ORDER_v]->map[cac]],t,p_data,cac)'}, 

            {'x': 'heaviside(t-v)', 
             'c': 'heaviside(t-par[ORDER_v][routers[ORDER_v]->map[cac]])'}, 

            {'x': 'heaviside((t-v))', 
             'c': 'heaviside(t-par[ORDER_v][routers[ORDER_v]->map[cac]])'}, 

            {'x': 'ramp(t-v)', 
             'c': 'ramp(t-par[ORDER_v][routers[ORDER_v]->map[cac]])'}, 

            {'x': 'correct_rate(v)', 
             'c': 'correct_rate(par[ORDER_v][routers[ORDER_v]->map[cac]],dt)'}, 
        ]
            
        for t in terms:
            self.assertEqual(self.m_drift.make_C_term(t['x'], False, human=False), t['c'])


    def test_cache_special_function_C(self):

        caches = map(lambda x: self.m_drift.make_C_term(x, True), ['sin(2*M_PI*(t/ONE_YEAR +r0))', 'sin(2*M_PI*(t/ONE_YEAR +r0))', 'terms_forcing(v)*sin(2*M_PI*(t/ONE_YEAR +r0))*terms_forcing(v)'])
        sf = self.m_drift.cache_special_function_C(caches, prefix='_sf[cac]')

        self.assertEqual(sf, ['sin(2*M_PI*(drifted[ORDER_drift__par_proc__r0][cac]+t/ONE_YEAR))', 'terms_forcing(par[ORDER_v][routers[ORDER_v]->map[cac]],t,p_data,cac)'])
        self.assertEqual(caches, ['_sf[cac][0]', '_sf[cac][0]', 'pow(_sf[cac][1],2)*_sf[cac][0]'])
        
    def test_eval_Q(self):
        calc_Q = self.m_noise.eval_Q()

        # testing env sto only
        term = '((((r0/N*v*I)*S)*((sto)**2))*((r0/N*v*I)*S)))'
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][0][0],'((-1)*'+term+'*(-1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][0][1],'((-1)*'+term+'*(1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][0][2],0)
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][0][3],'((-1)*'+term+'*(1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][0][4],'((-1)*'+term+'*(1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][1][0],'((1)*'+term+'*(-1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][1][1],'((1)*'+term+'*(1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][1][2],0)
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][1][3],'((1)*'+term+'*(1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][1][4],'((1)*'+term+'*(1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][2][0],0)
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][2][1],0)
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][2][2],0)
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][2][3],0)
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][2][4],0)
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][3][0],'((1)*'+term+'*(-1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][3][1],'((1)*'+term+'*(1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][3][2],0)
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][3][3],'((1)*'+term+'*(1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][3][4],'((1)*'+term+'*(1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][4][0],'((1)*'+term+'*(-1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][4][1],'((1)*'+term+'*(1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][4][2],0)
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][4][3],'((1)*'+term+'*(1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][4][4],'((1)*'+term+'*(1)')

        # testing dem sto only
        term1 = '(mu_b*N))'
        term2 = '((r0/N*v*I)*S))'
        term3 = '((correct_rate(v))*I))'
        term4 = '((mu_d)*S))'
        term5 = '((mu_d)*I))'
        self.assertEqual(calc_Q["no_env_sto"]["Q"][0][0],'((1)*'+term1+'*(1) + ((-1)*'+term2+'*(-1) + ((-1)*'+term4+'*(-1)')
        self.assertEqual(calc_Q["no_env_sto"]["Q"][0][1],'((-1)*'+term2+'*(1)')
        self.assertEqual(calc_Q["no_env_sto"]["Q"][0][2],0)
        self.assertEqual(calc_Q["no_env_sto"]["Q"][0][3],'((-1)*'+term2+'*(1)')
        self.assertEqual(calc_Q["no_env_sto"]["Q"][0][4],'((-1)*'+term2+'*(1)')
        self.assertEqual(calc_Q["no_env_sto"]["Q"][1][0],'((1)*'+term2+'*(-1)')
        self.assertEqual(calc_Q["no_env_sto"]["Q"][1][1],'((1)*'+term2+'*(1) + ((-1)*'+term3+'*(-1) + ((-1)*'+term5+'*(-1)' )
        self.assertEqual(calc_Q["no_env_sto"]["Q"][1][2],'((-1)*'+term3+'*(1) + ((-1)*'+term5+'*(1)')
        self.assertEqual(calc_Q["no_env_sto"]["Q"][1][3],'((1)*'+term2+'*(1)')
        self.assertEqual(calc_Q["no_env_sto"]["Q"][1][4],'((1)*'+term2+'*(1) + ((-1)*'+term3+'*(-1) + ((-1)*'+term5+'*(-1)')
        self.assertEqual(calc_Q["no_env_sto"]["Q"][2][0],0)
        self.assertEqual(calc_Q["no_env_sto"]["Q"][2][1],'((1)*'+term3+'*(-1) + ((1)*'+term5+'*(-1)')
        self.assertEqual(calc_Q["no_env_sto"]["Q"][2][2],'((1)*'+term3+'*(1) + ((1)*'+term5+'*(1)')
        self.assertEqual(calc_Q["no_env_sto"]["Q"][2][3],0)
        self.assertEqual(calc_Q["no_env_sto"]["Q"][2][4],'((1)*'+term3+'*(-1) + ((1)*'+term5+'*(-1)')       
        self.assertEqual(calc_Q["no_env_sto"]["Q"][3][0],'((1)*'+term2+'*(-1)')
        self.assertEqual(calc_Q["no_env_sto"]["Q"][3][1],'((1)*'+term2+'*(1)')
        self.assertEqual(calc_Q["no_env_sto"]["Q"][3][2],0)
        self.assertEqual(calc_Q["no_env_sto"]["Q"][3][3],'((1)*'+term2+'*(1)')
        self.assertEqual(calc_Q["no_env_sto"]["Q"][3][4],'((1)*'+term2+'*(1)')
        self.assertEqual(calc_Q["no_env_sto"]["Q"][4][0],'((1)*'+term2+'*(-1)')
        self.assertEqual(calc_Q["no_env_sto"]["Q"][4][1],'((1)*'+term2+'*(1) + ((-1)*'+term3+'*(-1) + ((-1)*'+term5+'*(-1)')
        self.assertEqual(calc_Q["no_env_sto"]["Q"][4][2],'((-1)*'+term3+'*(1) + ((-1)*'+term5+'*(1)')
        self.assertEqual(calc_Q["no_env_sto"]["Q"][4][3],'((1)*'+term2+'*(1)')
        self.assertEqual(calc_Q["no_env_sto"]["Q"][4][4],'((1)*'+term2+'*(1) + ((-1)*'+term3+'*(-1) + ((-1)*'+term5+'*(-1)')

        #print(calc_Q["no_env_sto"]["Q_proc"])

    
    def test_eval_Q_tricky_cases(self):

        calc_Q = self.m_noise2.eval_Q()
        # testing env sto only for m_noise2 : WN on U->S
        term = '(((mu_b*N)*((sto)**2))*(mu_b*N)))'
        for i in range(5):
            for j in range(5):
                if i==0 and j == 0:
                    self.assertEqual(calc_Q["no_dem_sto"]["Q"][i][j],'((1)*'+term+'*(1)')
                else:
                    self.assertEqual(calc_Q["no_dem_sto"]["Q"][i][j],0)


        calc_Q = self.m_noise3.eval_Q()
        # testing env sto only for m_noise3 : WN on I->R
        term = '((((correct_rate(v))*I)*((sto)**2))*((correct_rate(v))*I)))'
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][0][0],0)
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][0][1],0)
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][0][2],0)
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][0][3],0)
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][0][4],0)
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][1][0],0)
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][1][1],'((-1)*'+term+'*(-1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][1][2],'((-1)*'+term+'*(1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][1][3],0)
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][1][4],'((-1)*'+term+'*(-1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][2][0],0)
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][2][1],'((1)*'+term+'*(-1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][2][2],'((1)*'+term+'*(1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][2][3],0)
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][2][4],'((1)*'+term+'*(-1)')       
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][3][0],0)
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][3][1],0)
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][3][2],0)
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][3][3],0)
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][3][4],0)
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][4][0],0)
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][4][1],'((-1)*'+term+'*(-1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][4][2],'((-1)*'+term+'*(1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][4][3],0)
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][4][4],'((-1)*'+term+'*(-1)')
        

        calc_Q = self.m_noise4.eval_Q()
        # testing env sto only for m_noise4 : WN on I->U
        term = '((((mu_d)*I)*((sto)**2))*((mu_d)*I)))'
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][0][0],0)
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][0][1],0)
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][0][2],0)
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][0][3],0)
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][0][4],0)
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][1][0],0)
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][1][1],'((-1)*'+term+'*(-1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][1][2],'((-1)*'+term+'*(1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][1][3],0)
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][1][4],'((-1)*'+term+'*(-1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][2][0],0)
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][2][1],'((1)*'+term+'*(-1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][2][2],'((1)*'+term+'*(1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][2][3],0)
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][2][4],'((1)*'+term+'*(-1)')       
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][3][0],0)
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][3][1],0)
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][3][2],0)
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][3][3],0)
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][3][4],0)
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][4][0],0)
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][4][1],'((-1)*'+term+'*(-1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][4][2],'((-1)*'+term+'*(1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][4][3],0)
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][4][4],'((-1)*'+term+'*(-1)')

        calc_Q = self.m_noise5.eval_Q()
        # testing env sto only for m_noise5 : WN on R->U
        for i in range(5):
            for j in range(5):
                self.assertEqual(calc_Q["no_dem_sto"]["Q"][i][j],0)

        calc_Q = self.m_noise6.eval_Q()
        # testing env sto only for m_noise6 : correlated WN on I->R and S->I
        term1 = '((r0/N*v*I)*S)'
        term2 = '((correct_rate(v))*I)'
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][0][0],'((-1)*(('+term1+'*((sto)**2))*'+term1+'))*(-1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][0][1],'((-1)*(('+term1+'*((sto)**2))*'+term1+'))*(1) + ((-1)*(('+term1+'*((sto)**2))*'+term2+'))*(-1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][0][2],'((-1)*(('+term1+'*((sto)**2))*'+term2+'))*(1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][0][3],'((-1)*(('+term1+'*((sto)**2))*'+term1+'))*(1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][0][4],'((-1)*(('+term1+'*((sto)**2))*'+term1+'))*(1) + ((-1)*(('+term1+'*((sto)**2))*'+term2+'))*(-1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][1][0],'((1)*(('+term1+'*((sto)**2))*'+term1+') + (-1)*(('+term2+'*((sto)**2))*'+term1+'))*(-1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][1][1],'((1)*(('+term1+'*((sto)**2))*'+term1+') + (-1)*(('+term2+'*((sto)**2))*'+term1+'))*(1) + ((1)*(('+term1+'*((sto)**2))*'+term2+') + (-1)*(('+term2+'*((sto)**2))*'+term2+'))*(-1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][1][2],'((1)*(('+term1+'*((sto)**2))*'+term2+') + (-1)*(('+term2+'*((sto)**2))*'+term2+'))*(1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][1][3],'((1)*(('+term1+'*((sto)**2))*'+term1+') + (-1)*(('+term2+'*((sto)**2))*'+term1+'))*(1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][1][4],'((1)*(('+term1+'*((sto)**2))*'+term1+') + (-1)*(('+term2+'*((sto)**2))*'+term1+'))*(1) + ((1)*(('+term1+'*((sto)**2))*'+term2+') + (-1)*(('+term2+'*((sto)**2))*'+term2+'))*(-1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][2][0],'((1)*(('+term2+'*((sto)**2))*'+term1+'))*(-1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][2][1],'((1)*(('+term2+'*((sto)**2))*'+term1+'))*(1) + ((1)*(('+term2+'*((sto)**2))*'+term2+'))*(-1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][2][2],'((1)*(('+term2+'*((sto)**2))*'+term2+'))*(1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][2][3],'((1)*(('+term2+'*((sto)**2))*'+term1+'))*(1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][2][4],'((1)*(('+term2+'*((sto)**2))*'+term1+'))*(1) + ((1)*(('+term2+'*((sto)**2))*'+term2+'))*(-1)')       
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][3][0],'((1)*(('+term1+'*((sto)**2))*'+term1+'))*(-1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][3][1],'((1)*(('+term1+'*((sto)**2))*'+term1+'))*(1) + ((1)*(('+term1+'*((sto)**2))*'+term2+'))*(-1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][3][2],'((1)*(('+term1+'*((sto)**2))*'+term2+'))*(1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][3][3],'((1)*(('+term1+'*((sto)**2))*'+term1+'))*(1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][3][4],'((1)*(('+term1+'*((sto)**2))*'+term1+'))*(1) + ((1)*(('+term1+'*((sto)**2))*'+term2+'))*(-1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][4][0],'((1)*(('+term1+'*((sto)**2))*'+term1+') + (-1)*(('+term2+'*((sto)**2))*'+term1+'))*(-1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][4][1],'((1)*(('+term1+'*((sto)**2))*'+term1+') + (-1)*(('+term2+'*((sto)**2))*'+term1+'))*(1) + ((1)*(('+term1+'*((sto)**2))*'+term2+') + (-1)*(('+term2+'*((sto)**2))*'+term2+'))*(-1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][4][2],'((1)*(('+term1+'*((sto)**2))*'+term2+') + (-1)*(('+term2+'*((sto)**2))*'+term2+'))*(1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][4][3],'((1)*(('+term1+'*((sto)**2))*'+term1+') + (-1)*(('+term2+'*((sto)**2))*'+term1+'))*(1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][4][4],'((1)*(('+term1+'*((sto)**2))*'+term1+') + (-1)*(('+term2+'*((sto)**2))*'+term1+'))*(1) + ((1)*(('+term1+'*((sto)**2))*'+term2+') + (-1)*(('+term2+'*((sto)**2))*'+term2+'))*(-1)')

        calc_Q = self.m_noise7.eval_Q()
        # testing env sto only for m_noise7 : uncorrelated WN on I->R and S->I
        term1 = '((r0/N*v*I)*S)'
        term2 = '((correct_rate(v))*I)'
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][0][0],'((-1)*(('+term1+'*((sto)**2))*'+term1+'))*(-1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][0][1],'((-1)*(('+term1+'*((sto)**2))*'+term1+'))*(1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][0][2],0)
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][0][3],'((-1)*(('+term1+'*((sto)**2))*'+term1+'))*(1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][0][4],'((-1)*(('+term1+'*((sto)**2))*'+term1+'))*(1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][1][0],'((1)*(('+term1+'*((sto)**2))*'+term1+'))*(-1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][1][1],'((1)*(('+term1+'*((sto)**2))*'+term1+'))*(1) + ((-1)*(('+term2+'*((sto)**2))*'+term2+'))*(-1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][1][2],'((-1)*(('+term2+'*((sto)**2))*'+term2+'))*(1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][1][3],'((1)*(('+term1+'*((sto)**2))*'+term1+'))*(1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][1][4],'((1)*(('+term1+'*((sto)**2))*'+term1+'))*(1) + ((-1)*(('+term2+'*((sto)**2))*'+term2+'))*(-1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][2][0],0)
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][2][1],'((1)*(('+term2+'*((sto)**2))*'+term2+'))*(-1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][2][2],'((1)*(('+term2+'*((sto)**2))*'+term2+'))*(1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][2][3],0)
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][2][4],'((1)*(('+term2+'*((sto)**2))*'+term2+'))*(-1)')       
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][3][0],'((1)*(('+term1+'*((sto)**2))*'+term1+'))*(-1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][3][1],'((1)*(('+term1+'*((sto)**2))*'+term1+'))*(1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][3][2],0)
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][3][3],'((1)*(('+term1+'*((sto)**2))*'+term1+'))*(1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][3][4],'((1)*(('+term1+'*((sto)**2))*'+term1+'))*(1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][4][0],'((1)*(('+term1+'*((sto)**2))*'+term1+'))*(-1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][4][1],'((1)*(('+term1+'*((sto)**2))*'+term1+'))*(1) + ((-1)*(('+term2+'*((sto)**2))*'+term2+'))*(-1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][4][2],'((-1)*(('+term2+'*((sto)**2))*'+term2+'))*(1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][4][3],'((1)*(('+term1+'*((sto)**2))*'+term1+'))*(1)')
        self.assertEqual(calc_Q["no_dem_sto"]["Q"][4][4],'((1)*(('+term1+'*((sto)**2))*'+term1+'))*(1) + ((-1)*(('+term2+'*((sto)**2))*'+term2+'))*(-1)')


    def test_jac(self):
        step_ode_sde = self.m_drift.step_ode_sde()
        jac = self.m_drift.jac(step_ode_sde['sf'])


        # testing jac
        # S ode - ((r0/N*v*I)*S) - ((mu_d)*S) + (mu_b*N)
        self.assertEqual(jac["caches"][jac["jac"][0][0]],self.m_drift.make_C_term('- ((r0/N*v*I)) - ((mu_d))', False, human=False))
        self.assertEqual(jac["caches"][jac["jac"][0][1]],self.m_drift.make_C_term('- ((r0/N*v)*S)', False, human=False))
        self.assertEqual(jac["caches"][jac["jac_drift"][0][0]["value"]],self.m_drift.make_C_term('- ((1/N*v*I)*S)', False, human=False)) # the derivative is computed with regards to r0 and not transf(r0), as the latter is taken care of on runtime because it depends on the transformation.
        # I ode - ((v)*I) - ((mu_d)*I) + ((r0/N*v*I)*S)
        self.assertEqual(jac["caches"][jac["jac"][1][0]],self.m_drift.make_C_term(' ((r0/N*v*I)) ', False, human=False))
        self.assertEqual(jac["caches"][jac["jac"][1][1]],self.m_drift.make_C_term('- ((v)) - ((mu_d)) + ((r0/N*v)*S)', False, human=False))
        self.assertEqual(jac["caches"][jac["jac_drift"][1][0]["value"]],self.m_drift.make_C_term('((1/N*v*I)*S)', False, human=False))
        
        # testing jac_obs
        # inc_out ((v)*I) + ((mu_d)*I)
        self.assertEqual(jac["caches"][jac["jac_obs"][0][0]],self.m_drift.make_C_term('0', False, human=False))
        self.assertEqual(jac["caches"][jac["jac_obs"][0][1]],self.m_drift.make_C_term('((v)) + ((mu_d))', False, human=False))
        self.assertEqual(jac["caches"][jac["jac_obs_drift"][0][0]["value"]],self.m_drift.make_C_term('0', False, human=False))
        # inc_in ((r0/N*v*I)*S)
        self.assertEqual(jac["caches"][jac["jac_obs"][1][0]],self.m_drift.make_C_term('((r0/N*v*I))', False, human=False))
        self.assertEqual(jac["caches"][jac["jac_obs"][1][1]],self.m_drift.make_C_term('((r0/N*v)*S)', False, human=False))
        self.assertEqual(jac["caches"][jac["jac_obs_drift"][1][0]["value"]],self.m_drift.make_C_term('((1/N*v*I)*S)', False, human=False))
        # prev - ((v)*I) - ((mu_d)*I) + ((r0/N*v*I)*S)
        self.assertEqual(jac["caches"][jac["jac_obs"][2][0]],self.m_drift.make_C_term('((r0/N*v*I))', False, human=False))
        self.assertEqual(jac["caches"][jac["jac_obs"][2][1]],self.m_drift.make_C_term('- ((v)) - ((mu_d)) + ((r0/N*v)*S)', False, human=False))
        self.assertEqual(jac["caches"][jac["jac_obs_drift"][2][0]["value"]],self.m_drift.make_C_term('((1/N*v*I)*S)', False, human=False))

    def test_jac_tricky_cases(self):

        # testing if remainder is well dealt with
        step_ode_sde = self.m_drift2.step_ode_sde()
        jac = self.m_drift2.jac(step_ode_sde['sf'])


        # jac_obs
        # prev - ((v)*I) - ((mu_d)*I) + ((r0/N*v*I)*S) + ((correct_rate(v))*(N-S-I))
        self.assertEqual(jac["caches"][jac["jac_obs"][2][0]],self.m_drift.make_C_term('((r0/N*v*I)) -  correct_rate(v)', True, human=False))
        self.assertEqual(jac["caches"][jac["jac_obs"][2][1]],self.m_drift.make_C_term('- ((v)) - ((mu_d)) + ((r0/N*v)*S) -  correct_rate(v)', True, human=False))
        self.assertEqual(jac["caches"][jac["jac_obs_drift"][2][0]["value"]],self.m_drift.make_C_term('((1/N*v*I)*S)', True, human=False))