简体   繁体   中英

Python solve ODE system with solve_ivp

I've been trying to solve a system of ODE's with scipys solve_ivp, which is a mean field approximation of a hierarchically organized tissue model, where I want to quantify the number of cells at level 'k' with 'm' number of mutations at a given time point. Here is the equation itself:

the equations

My goal is to calculate the number of cells which have 1,2,3... number of mutations, which can be obtained by knowing the number of cells in the entire system having at least 1,2,3... number of mutations which is: M(m) = \\sum_{k=0,n} \\sum_{l=m,inf} N_{k,l}, where n is the last hierarchical level. The problem is, that the resulting cell numbers of these equations include those cells also, which have not acquired a new mutation, but just inherited it from its mother cell. I want to count those cells which acquired a new mutation.

So my problem is that I having a hard time modifying the equations, all I want to do is setting a "counter" where I can add at every iteration a certain proportion of cells, while I do not modify my original equations which governing the system dynamics.

Here is my code:

#!/usr/bin/python

import os, shutil, time, sys, math
from sys import *
import numpy as np  
import matplotlib.pyplot as plt 
from scipy.integrate import solve_ivp
from mpmath import *
mp.dps = 30

n=3 # number of levels
g = 3.0 # a parameter of the tissue

deltas = [0]*(n+2) # differentiation rates
Nk = [1.0]*(n+2) # number of cells prescribed to a level
maxMut = 10  
N = 1024*Nk[0]  # number of cells generated over the lifetime of the tissue
tlife = N
sumNk = 0

for k in range(len(Nk)-1):
    sumNk += Nk[k]

for l in range(0,n):
    deltas[l] = (1./g)**(n-1-l)
deltas[n]=2.0
deltas[n+1] = 0


print(deltas)

Nkmt = np.zeros((maxMut,n+1)).flatten() # I store the equations here

def Nt(t,Nkmt):
    retVec= []

    for k in range(len(Nkmt)):

        if k%maxMut==0 and k>0 and k<n*maxMut: # wild type non term
            retVec.append(deltas[int(floor(k/float(maxMut)))-1] * (Nkmt[k-maxMut]/Nk[int(floor(k/float(maxMut)))-1] - Nkmt[k]/Nk[int(floor(k/float(maxMut)))]+ mu * ( (0-Nkmt[k-maxMut])/Nk[int(floor(k/float(maxMut)))-1] - 2*(0-Nkmt[k])/Nk[int(floor(k/float(maxMut)))] ) )+ deltas[int(floor(k/float(maxMut)))] * mu * (0-Nkmt[k])/Nk[int(floor(k/float(maxMut)))])

        elif k<maxMut and k>0: # 0th level with mutation
            retVec.append(deltas[int(floor(k/float(maxMut)))] * mu * (Nkmt[k-1]-Nkmt[k])/Nk[int(floor(k/float(maxMut)))])
        elif k==0: # 0th level wild type
            retVec.append(deltas[int(floor(k/float(maxMut)))] * mu * (0-Nkmt[k])/Nk[int(floor(k/float(maxMut)))])
        elif k>n*maxMut: # term level with mutation
            retVec.append( ((deltas[int(floor(k/float(maxMut)))-1]/Nk[int(floor(k/float(maxMut)))-1])*Nkmt[k-maxMut])+ mu*( (deltas[int(floor(k/float(maxMut)))-1]/Nk[int(floor(k/float(maxMut)))-1])*Nkmt[k-maxMut-1])- mu*( (deltas[int(floor(k/float(maxMut)))-1]/Nk[int(floor(k/float(maxMut)))-1])*Nkmt[k-maxMut]))    
        elif k==n*maxMut: # term level wild type
            retVec.append( ((deltas[int(floor(k/float(maxMut)))-1]/Nk[int(floor(k/float(maxMut)))-1])*Nkmt[k-maxMut])- mu*( (deltas[int(floor(k/float(maxMut)))-1]/Nk[int(floor(k/float(maxMut)))-1])*Nkmt[k-maxMut]))

        else: # everything else
            retVec.append(deltas[int(floor(k/float(maxMut)))-1] * (Nkmt[k-maxMut]/Nk[int(floor(k/float(maxMut)))-1] - Nkmt[k]/Nk[int(floor(k/float(maxMut)))]+ mu * ( (Nkmt[k-maxMut-1]-Nkmt[k-maxMut])/Nk[int(floor(k/float(maxMut)))-1] - 2*(Nkmt[k-1]-Nkmt[k])/Nk[int(floor(k/float(maxMut)))] ) )+ deltas[int(floor(k/float(maxMut)))] * mu * (Nkmt[k-1]-Nkmt[k])/Nk[int(floor(k/float(maxMut)))])
        return retVec

Nkmt = Nkmt.tolist()
initCond = [0]*(len(Nkmt))
M_Vec = [0]*maxMut
P_vec=[0]*maxMut

for k in range(len(Nkmt)):
    if k%maxMut==0 and k<(n+1)*maxMut:
        initCond[k] = Nk[int(floor(k/float(maxMut)))]
    else:
        initCond[k] = 0.0

file = open("Pmuem_Master_1.txt",'w+')

print(Nkmt,initCond)

for mut in range(0,20):  # here I tune the mutation rate
    mu = (1e-6)*(10**(1./4))**mut
    #mu = 0
    lspace = int(tlife/1.0)
    res = solve_ivp(Nt,(0,tlife),initCond,t_eval=np.linspace(0,tlife,lspace))# here I solve the system

    for m in range(len(M_Vec)):
        M_Vec[m]=0
    for m in range(0,len(Nkmt)):
        M_Vec[0]+=res.y[m].T[lspace-1]
        for n_mut in range(1,maxMut):
            if m%maxMut<n_mut:
                M_Vec[n_mut] += res.y[m].T[lspace-1] # here I sum all the mutants cells which have at least m mutations

    file.write(str(mu)+'\t')
    for m in range(1,maxMut):
        P_vec[m] = 1.0-exp(-(M_Vec[0]-M_Vec[m])/Nk[0])  # here I calculate the probabilities
        file.write(str(P_vec[m] )+'\t')
    file.write('\n')

    #print(M_Vec[0])
    print(M_Vec[0], sumNk,P_vec[1]/(1.0-exp(-2*N*mu/Nk[0])),(M_Vec[0]-M_Vec[1])/(2*N*mu),P_vec[1],)

file.close()


So the question again is, how can I add a "counter" with which at every iteration I can add a particular value to it which is a proportion of cells, which gained a new mutation, eg:

...
def Nt(t,Nkmt):
    retVec= []
    retVecE = []
    eq = 0
    for k in range(len(Nkmt)):
            ...
         elif k<maxMut and k>0: # 0th level with mutation
            #print("0th level with mutation",k,int(floor(k/float(maxMut))),k%maxMut,k-maxMut)
            retVec.append(deltas[int(floor(k/float(maxMut)))] * mu * (Nkmt[k-1]-Nkmt[k])/Nk[int(floor(k/float(maxMut)))])
            counter+= deltas[int(floor(k/float(maxMut)))] * mu * (Nkmt[k-1])/Nk[int(floor(k/float(maxMut)))]
            ...
...

Thank you in advance, I am also open to completely start the implementation from scratch if there is a better way to do this with python or c++ or mathematica or anything...

I could solve it

#!/usr/bin/python

import os, shutil, time, sys, math
from sys import *
import numpy as np  
import matplotlib.pyplot as plt 
from scipy.integrate import solve_ivp, odeint
from mpmath import *
mp.dps = 30
N0 = 1 
rm = 2 
nt = 1
mg2 = 1
inf = 25 
threshold = 0.0000000001

porq = 'p'

pkqk = 1

def p(g):
    if porq == "p":
        return float(pkqk)
    else:
        return 2.0/(q(g)*g) 

def q(g):
    if porq == "q":
        return float(pkqk)
    else:
        return 2.0/(p(g)*g) 


def ddpd(m,g,s):
    return 1/(1 + q(g)*(m*s*(g - 1) - 1))

def mc(g, s): 
    return ceil(1/(s*(g - 1)))


def Dtr(g,k):
    return k*(g-1)

def Dli(g,k,n):
    return NpN0/g**(n-1) + Dtr(g,k)

def Pmul(g,k,n):
    if(k==n):
        return 2.0/g
    else:
        return 1.0

def Dadd(g,k,n):
    if(k==n):
        return 0
    else:
        return (1-p(g))/2.0

def P(mu,m,g,k,n):
    if(k-1>=0):
        return (mu**m/math.gamma(m + 1))*((Dli(g, k, n) + Dadd(g, k, n) - 1.5)**
    m - (Dtr(g, k) + Dadd(g, k, n) - 1.5)**m)*(g**k)*Pmul(g, k, n)
    else:
        return (mu**m/math.gamma(m + 1))*(Dli(g, 0, n))**m

fileError = open("Error.txt",'w+')
file = open("Pmuem_Master_"+sys.argv[1]+"_"+str(1e-5)+".txt",'w+')
for gammas in range(int(sys.argv[2]),int(sys.argv[3])):
    print(gammas)
    n=int(sys.argv[1])
    g = 2.0+gammas*0.5

    deltas = [0]*(n+2)
    Nk = [1e20 ]*(n+2)
    maxMut = 12
    N = 1e7*Nk[0]
    tlife = N
    NpN0 = N
    sumNk = 0
    for k in range(len(Nk)-1):
        sumNk += Nk[k]

    for l in range(0,n):
        deltas[l] = (1./g)**(n-1-l)
    deltas[n]=2.0
    deltas[n+1] = 0


    p=1

    #íp=(2.0/g)

    print(deltas)

    Nkmt = np.zeros((maxMut,n+1)).flatten() # Pre-allocate matrix
    Ekmt = np.zeros((maxMut,n+1)).flatten() # Pre-allocate matrix

    def Nt(t,Nkmt):
        retVec= []
        retVecE = []
        for k in range(len(Ekmt)):
            # top level differentiation off
            
            if k%maxMut==0 and k>0 and k<n*maxMut: # wild type non term
                #print("wild type non term.",k,int(floor(k/float(maxMut))),k%maxMut,k-maxMut)
                retVec.append(deltas[int(floor(k/float(maxMut)))-1] * (Nkmt[k-maxMut]/Nk[int(floor(k/float(maxMut)))-1] - Nkmt[k]/Nk[int(floor(k/float(maxMut)))]+ mu * ( (0-Nkmt[k-maxMut])/Nk[int(floor(k/float(maxMut)))-1] - 2*(0-Nkmt[k])/Nk[int(floor(k/float(maxMut)))] ) )+ deltas[int(floor(k/float(maxMut)))] * mu * (0-Nkmt[k])/Nk[int(floor(k/float(maxMut)))])
            
            elif k<maxMut and k>0: # 0th level with mutation
                #print("0th level with mutation",k,int(floor(k/float(maxMut))),k%maxMut,k-maxMut)
                retVec.append(deltas[int(floor(k/float(maxMut)))] * mu * (Nkmt[k-1]-Nkmt[k])/Nk[int(floor(k/float(maxMut)))])
            elif k==0: # 0th level wild type
                #print("0th level wild type",k,int(floor(k/float(maxMut))),k%maxMut,k-maxMut)
                retVec.append(deltas[int(floor(k/float(maxMut)))] * mu * (0-Nkmt[k])/Nk[int(floor(k/float(maxMut)))])
            elif k>n*maxMut: # term level with mutation
                #print("term level with mutation",k,int(floor(k/float(maxMut))),k%maxMut,k-maxMut)
                retVec.append( ((deltas[int(floor(k/float(maxMut)))-1]/Nk[int(floor(k/float(maxMut)))-1])*Nkmt[k-maxMut])+ mu*( (deltas[int(floor(k/float(maxMut)))-1]/Nk[int(floor(k/float(maxMut)))-1])*Nkmt[k-maxMut-1])- mu*( (deltas[int(floor(k/float(maxMut)))-1]/Nk[int(floor(k/float(maxMut)))-1])*Nkmt[k-maxMut]))    
            elif k==n*maxMut: # term level wild type
                #print("term level wild type",k,int(floor(k/float(maxMut))),k%maxMut,k-maxMut)
                retVec.append( ((deltas[int(floor(k/float(maxMut)))-1]/Nk[int(floor(k/float(maxMut)))-1])*Nkmt[k-maxMut])- mu*( (deltas[int(floor(k/float(maxMut)))-1]/Nk[int(floor(k/float(maxMut)))-1])*Nkmt[k-maxMut]))

            else: # everything else
                #print("everything else",k,int(floor(k/float(maxMut))),k%maxMut,k-maxMut)
                retVec.append(deltas[int(floor(k/float(maxMut)))-1] * (Nkmt[k-maxMut]/Nk[int(floor(k/float(maxMut)))-1] - Nkmt[k]/Nk[int(floor(k/float(maxMut)))]+ mu * ( (Nkmt[k-maxMut-1]-Nkmt[k-maxMut])/Nk[int(floor(k/float(maxMut)))-1] - 2*(Nkmt[k-1]-Nkmt[k])/Nk[int(floor(k/float(maxMut)))] ) )+ deltas[int(floor(k/float(maxMut)))] * mu * (Nkmt[k-1]-Nkmt[k])/Nk[int(floor(k/float(maxMut)))])
            

            if k%maxMut==0 and k>0 and k<n*maxMut: # wild type non term
                #print("wild type non term.",k,int(floor(k/float(maxMut))),k%maxMut,k-maxMut)
                retVecE.append(0)
            
            elif k<maxMut and k>0: # 0th level with mutation
                #print("0th level with mutation",k,int(floor(k/float(maxMut))),k%maxMut,k-maxMut)
                retVecE.append(deltas[int(floor(k/float(maxMut)))-1] * (mu * ( (Nkmt[k-maxMut-1])/Nk[int(floor(k/float(maxMut)))-1] - 2*(Nkmt[k-1])/Nk[int(floor(k/float(maxMut)))] ) )+ deltas[int(floor(k/float(maxMut)))] * mu * (Nkmt[k-1])/Nk[int(floor(k/float(maxMut)))])
            elif k==0: # 0th level wild type
                #print("0th level wild type",k,int(floor(k/float(maxMut))),k%maxMut,k-maxMut)
                retVecE.append(0)
            elif k>n*maxMut: # term level with mutation
                #print("term level with mutation",k,int(floor(k/float(maxMut))),k%maxMut,k-maxMut)
                retVecE.append(deltas[int(floor(k/float(maxMut)))-1] * (mu * ( (Nkmt[k-maxMut-1])/Nk[int(floor(k/float(maxMut)))-1] - 2*(Nkmt[k-1])/Nk[int(floor(k/float(maxMut)))] ) )+ deltas[int(floor(k/float(maxMut)))] * mu * (Nkmt[k-1])/Nk[int(floor(k/float(maxMut)))])    
            elif k==n*maxMut: # term level wild type
                #print("term level wild type",k,int(floor(k/float(maxMut))),k%maxMut,k-maxMut)
                retVecE.append(0)

            else: # everything else
                #print("everything else",k,int(floor(k/float(maxMut))),k%maxMut,k-maxMut)
                retVecE.append(deltas[int(floor(k/float(maxMut)))-1] * (mu * ( (Nkmt[k-maxMut-1])/Nk[int(floor(k/float(maxMut)))-1] - 2*(Nkmt[k-1])/Nk[int(floor(k/float(maxMut)))] ) )+ deltas[int(floor(k/float(maxMut)))] * mu * (Nkmt[k-1])/Nk[int(floor(k/float(maxMut)))])

            
        return retVec+retVecE

    #Nkmt = np.append(Nkmt,0)
    Nkmt = Nkmt.tolist()
    Ekmt = Ekmt.tolist()

    Nkmt = Nkmt+Ekmt

    initCond = [0]*(len(Nkmt))
    M_Vec = [0]*maxMut
    P_vec=[0]*maxMut



    for k in range(len(Nkmt)):
        if k%maxMut==0 and k<=n*maxMut :
            initCond[k] = Nk[int(floor(k/float(maxMut)))]
        else:
            initCond[k] = 0.0
    
    print(len(Nkmt),len(initCond) )

    E = np.zeros((n+1,maxMut))
    ErrorSum = 0
    for mut in range(0,1):
        mu = 1e-5
        #mu = 0
        lspace = 10000
        print(np.linspace(0,tlife,lspace))
        res = solve_ivp(Nt,(0,tlife),initCond,t_eval=np.linspace(0,tlife,lspace), method = 'LSODA')
        #res = odeint(Nt,initCond,np.linspace(0,tlife,lspace))  
        '''
        #plotting results
        plt.ylim(0.01, N*10)
        plt.yscale('log')
        
        #plt.plot(res.t, res.y[1].T+res.y[maxMut+1].T+res.y[2*maxMut+1].T,color='green', label='mut1')
        
        for k in range(len(Nkmt)):
            labello = str(int(floor(k/maxMut)))+str(k%maxMut)
            plt.plot(res.t, res.y[k].T, label=labello)
            randpos = int(floor(k/maxMut))*800
            plt.text(res.t[-1-randpos], res.y[k].T[-1-randpos], labello)    
        plt.plot(res.t,2*res.t*mu,color='yellow', label='2*N*mu')
        #plt.legend()
        plt.plot(res.t, res.y[1].T+res.y[maxMut+1].T+res.y[2*maxMut+1].T+res.y[3*maxMut+1].T, label="mutossz")
        plt.show()

        print(res.y[1].T[-1],res.y[3].T[-1],res.y[5].T[-1])
        '''
        
        for m in range(len(M_Vec)):
            M_Vec[m]=0
        for m in range(0,len(Nkmt)):
            M_Vec[0]+=res.y[m].T[lspace-1]
        
            for n_mut in range(1,maxMut):
                if m%maxMut>=n_mut and m >= (n+1)*maxMut:
                    if M_Vec[n_mut]>=0:
                        M_Vec[n_mut] += res.y[m].T[lspace-1]
                    else:
                        continue
        file.write(str(g)+'\t')
        for m in range(1,maxMut):
            P_vec[m] = 1.0-exp(-(M_Vec[m])/Nk[0])
            file.write(str(P_vec[m] )+'\t')
        file.write('\n')
        
        #print(M_Vec[0])
        #print(M_Vec[0], sumNk,P_vec[1]/(1.0-exp(-2*N*mu/Nk[0])),(M_Vec[0]-M_Vec[1])/(2*N*mu),P_vec[1],)
file.close()

fileError.close()
    


The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM