Skip to content

Instantly share code, notes, and snippets.

@jeanpat jeanpat/Cellular.py
Last active Jul 15, 2018

Embed
What would you like to do?
Modules used in telomere length modelisation
# -*- coding: utf-8 -*-
"""
Created on Wed Mar 30 13:04:37 2016
@author: jeanpat
"""
import pandas as pn
from itertools import product
import ClassChromosome as K
import Genome as G
def init_genome(telomeres_distribution =
{"1":(15000,18000,9000,12000),
"2":(11000, 20000, 11050,19950)}):
'''telomeres_distribution is a dictionary:
{"1":(15000,18000,9000,12000), "2":(11000, 20000, 11050,19950)}
'''
if type(telomeres_distribution) != type(dict()):
raise NameError('Telomere length must be a dictionary "chrom1":(p1,q1,p2,q2)')
chrom_set = []
for tels in telomeres_distribution.keys():
t0 = telomeres_distribution[tels][0]#first homolog at pter
t1 = telomeres_distribution[tels][1]#first homolog at qter
t2 = telomeres_distribution[tels][2]#other homolog at pter
t3 = telomeres_distribution[tels][3]#other homolog at qter
w1 = K.Watson(ttaggg = t0, ccctaa = t1)
c1 = K.Crick(ttaggg = t1, ccctaa = t0)
w2 = K.Watson(ttaggg= t2, ccctaa = t3)
c2 = K.Crick(ttaggg= t3, ccctaa = t2)
#chrom_set.ap
chrom_set.append(K.Chromosome(watson=w1,crick=c1, name =str(tels),homolog='mat'))
chrom_set.append(K.Chromosome(watson=w2,crick=c2, name =str(tels),homolog='pat'))
return G.Genome(*chrom_set)
class Cell(object):
# def init_genome(self, telomeres_distribution = {"1":(15000,18000,9000,12000),
# "2":(11000, 20000, 11050,19950)}):
# '''telomeres_distribution is a dictionary:
# {"1":(15000,18000,9000,12000), "2":(11000, 20000, 11050,19950)}
#
# '''
# print "init_genome"
# if type(telomeres_distribution)<>type(dict()):
# raise NameError('Telomere length must be a dictionary "chrom1":(p1,q1,p2,q2)')
# chrom_set = []
# for tels in telomeres_distribution.keys():
# t0 = telomeres_distribution[tels][0]#first homolog at pter
# t1 = telomeres_distribution[tels][1]#first homolog at qter
# t2 = telomeres_distribution[tels][2]#other homolog at pter
# t3 = telomeres_distribution[tels][3]#other homolog at qter
#
# w1 = K.Watson(ttaggg = t0, ccctaa = t1)
# c1 = K.Crick(ttaggg = t1, ccctaa = t0)
#
# w2 = K.Watson(ttaggg= t2, ccctaa = t3)
# c2 = K.Crick(ttaggg= t3, ccctaa = t2)
# #chrom_set.ap
# chrom_set.append(K.Chromosome(watson=w1,crick=c1, name =str(tels),homolog='mat'))
# chrom_set.append(K.Chromosome(watson=w2,crick=c2, name =str(tels),homolog='pat'))
# return G.Genome(*chrom_set)
#
def __init__(self,division = 0,
genome = init_genome(),
short_telomere_threshold = 200,
telomerase = {'ON':False,
'Docking':(1000,0.95),
'Elongation':(200,0.95)}
):
self.division = division
#
#telomerase parametres
self.telomerase_par = telomerase
self.telomerase_ON = self.telomerase_par['ON']
#telomere lenght theshold (bp)for telomerase docking
#simulation of the D-loop opening:
self.docking_threshold = self.telomerase_par['Docking'][0]
#docking probability: bellow the docking threshold,
#the probability for the telomerase to dock is:
self.docking_proba = self.telomerase_par['Docking'][1]
# When telomerase is docked the TTAGGG motif is elongated
# by n bases (ex:200) with a probability of p (p=0.95):
self.tel_elongation = self.telomerase_par['Elongation'][0]
self.elongation_prob = self.telomerase_par['Elongation'][1]
#### GENOME initialization ####
self.genome = genome
self.short_telomere_threshold = short_telomere_threshold
self.genome_dataframe()
self.shortest_telo = self.scan_shortest_telomere()
if self.shortest_telo <= self.short_telomere_threshold:
## The cell becomes senescent, blocked in G0
self.G0 = True
else:
self.G0 = False
#def scan_shortest_telomere(self):
# df = self.genome_dataframe()
# return df.T.min()[0]
def scan_shortest_telomere(self):
df = self.genome_dataframe()
#telomeres_list = df.columns-['division']
telomeres_list = df.columns[1:]
shortest_telo = df.ix[:, telomeres_list ].min().min()
#print shortest_telo
return shortest_telo
def mitose(self):
# check if G_0 can be left
#print type(self.genome)
# trigger genome replication
self.shortest_telo = self.scan_shortest_telomere()
#print type(shortest_telo[0]),shortest_telo[0]
if self.shortest_telo <= self.short_telomere_threshold:
## The cell becomes senescent, blocked in G0
self.G0 = True
#return None
else:
self.genome.set_G1_to_G2()
#trigger telophase
son_genome = self.genome.G2_to_M()
#print self.division
self.division = self.division +1
self.genome_dataframe()
daughter_cell = Cell(division = self.division,
genome = son_genome,
telomerase = self.telomerase_par,
short_telomere_threshold = self.short_telomere_threshold)
# Check post replication if the shortest telomere is bellow threshold
#Check mother cell
self.shortest_telo = self.scan_shortest_telomere()
if self.shortest_telo <= self.short_telomere_threshold:
## The cell becomes senescent, blocked in G0
self.G0 = True
#Daughter cell: the telomere length is checked on initialisation. If the shortest telo
#of the daughter cell is bellow threshold, the daughter cell is blocked in G0
return daughter_cell
def genome_dataframe(self):
'''Return all the telomere in a pandas data_frame, one column per telomere
the homologs must be distinguished by a tag: eg:maternal,paternal
'''
chroms = self.genome.get_chromosomes_list()
homogs = self.genome.get_homologous_tags()
telo = {}
#telo['division'] = self.division
div_df = pn.DataFrame({'division' : self.division}, index = [0])
for telomeric in product(chroms,['pter','qter'], '_',homogs):
telo[''.join(telomeric)]= [self.genome.get_telo_length(pair=telomeric[0],
hog=telomeric[3],
tel=telomeric[1])]
self.telo_df = pn.DataFrame(telo)#pandas dataframe
self.telo_df = pn.concat([div_df,self.telo_df], axis = 1)
return self.telo_df
# -*- coding: utf-8 -*-
"""
Created on Thu Sep 6 11:29:52 2012
@author: Jean-Patrick Pommier
"""
from WatsonCrick import Watson, Crick
import random
class Chromosome(object):
def __init__(self,watson = Watson(ttaggg = 10001, ccctaa = 5000), crick = Crick(ttaggg = 5000, ccctaa = 10000), name ='1', homolog ='a'):
#print 'new chromosome'
watson.in_use = True
crick.in_use = True
self.name = name
self.homolog = homolog
self.phase = 'G1'
self.watson = watson
self.crick = crick
#Double strand DNA
self.chromatide = []
self.chromatide.append(self.watson)
self.chromatide.append(self.crick)
self.chromosome = []
self.chromosome.append(self.chromatide)#chromosome with one chromatid
def set_G1_to_G2(self):
self.phase = 'G2'
self.sister_chromatid1 = []
self.sister_chromatid2 = []
# temporary variables
self.ctd = self.chromosome.pop()
self.strand1 = self.ctd.pop()
self.strand2 = self.ctd.pop()
self.sister_chromatid1.append(self.strand1)
self.sister_chromatid1.append(self.strand1.replicate())
self.sister_chromatid2.append(self.strand2)
self.sister_chromatid2.append(self.strand2.replicate())
self.chromosome.append(self.sister_chromatid1)
self.chromosome.append(self.sister_chromatid2)
def segregate(self) :
'''gives two sister chromatids from metaphasic chromosome
'''
def getWatsonCrick_Index_in(chromatid):
if type(chromatid[0]) == Watson:
return 0, 1
else:
return 1, 0
if self.phase == 'G2':
index = random.randint(0,1)
#print index
# get one of the two chromatids of the G2 chromosome
self.sister_ctd1 = self.chromosome.pop(index)
w, c = getWatsonCrick_Index_in(self.sister_ctd1)
#Back to G1 state in the cell cycle after chromosome segregation
self.phase = 'G1'
son = Chromosome(self.sister_ctd1.pop(w),self.sister_ctd1.pop(), name = self.name, homolog=self.homolog)
return son
else:
raise NameError ('chromosome segregation only on metaphasic chrom!')
#==============================================================================
#
#==============================================================================
def get_Crick(self):
'''Returns a single strand of type Crick
'''
if type(self.chromosome[0][0]) == Crick:
return self.chromosome[0][0]
else:
return self.chromosome[0][1]
def get_Watson(self):
'''Returns a single strand of type Watson
'''
if type(self.chromosome[0][0]) == Watson:
return self.chromosome[0][0]
else:
return self.chromosome[0][1]
def get_pter_G1(self, motif='ccctaa'):
'''telomere length at pter = nber of ccctaa motifs on Crick single strand
telomere length at pter = nber of ttaggg motifs on Watson single strand
'''
#get index of crick strand in chromatid[]
if motif == 'ccctaa':
if self.phase == 'G1':
if type(self.chromosome[0][0]) == Crick:
return self.chromosome[0][0].getCCCTAA()
else:
return self.chromosome[0][1].getCCCTAA()
else:
raise NameError('only on G1 chromosome')
elif motif =='ttaggg':
if self.phase == 'G1':
if type(self.chromosome[0][0]) == Watson:
return self.chromosome[0][0].getTTAGGG()
else:
return self.chromosome[0][1].getTTAGGG()
else:
raise NameError('only on G1 chromosome')
def get_qter_G1(self,motif='ccctaa'):
'''telomere length at qter = nber of ccctaa motifs on Watson single strand
telomere length at qter = nber of ttaggg motifs on Crick single strand
'''
#get index of crick strand in chromatid[]
if motif == 'ccctaa':
if self.phase == 'G1':
if type(self.chromosome[0][0]) == Watson:
return self.chromosome[0][0].getCCCTAA()
else:
return self.chromosome[0][1].getCCCTAA()
else:
raise NameError('only on G1 chromosome')
elif motif =='ttaggg':#ERROR
if self.phase == 'G1':
if type(self.chromosome[0][0]) == Crick:
return self.chromosome[0][0].getTTAGGG()
else:
return self.chromosome[0][1].getTTAGGG()
else:
raise NameError('only on G1 chromosome')
def get_pter_G2(self,motif='ccctaa'):
'''telomere length at pter = nber of ccctaa motifs on Crick single strand
telomere length at pter = nber of ttaggg motifs on Watson single strand
'''
def getCrickindex_chromatid1():
'''get the index of the Crick strand in chromatid1
'''
if type(self.sister_chromatid1[0]) == Crick:
return 0
else:
return 1
def getCrickindex_chromatid2():
'''get the index of the Crick strand in chromatid2
'''
if type(self.sister_chromatid2[0]) == Crick:
return 0
else:
return 1
def getWatsonindex_chromatid1():
if type(self.sister_chromatid1[0]) == Watson:
return 0
else:
return 1
def getWatsonindex_chromatid2():
if type(self.sister_chromatid2[0]) == Watson:
return 0
else:
return 1
if self.phase == 'G2':
if motif == 'ccctaa':
c1 = getCrickindex_chromatid1()
c2 = getCrickindex_chromatid2()
return self.sister_chromatid1[c1].getCCCTAA(),self.sister_chromatid2[c2].getCCCTAA()
elif motif == 'ttaggg':
w1 = getWatsonindex_chromatid1()
w2 = getWatsonindex_chromatid2()
ttaggg1 = self.sister_chromatid1[w1].getTTAGGG()
ttaggg2 = self.sister_chromatid2[w2].getTTAGGG()
return ttaggg1, ttaggg2
else:
raise NameError('only on G2 chromosome')
def get_qter_G2(self,motif='ccctaa'):
'''telomere length at qter = nber of ccctaa motifs on Watson single strand
telomere length at qter = nber of ttaggg motifs on Crick single strand
on each chromatid
'''
#get index of Watson strand in chromatid[]
def getWatsonindex_chromatid1():
'''get the index of the Watson strand in chromatid1
'''
if type(self.sister_chromatid1[0]) == Watson:
return 0
else:
return 1
def getWatsonindex_chromatid2():
'''get the index of the Watson strand in chromatid2
'''
if type(self.sister_chromatid2[0]) == Watson:
return 0
else:
return 1
def getCrickindex_chromatid1():
'''get the index of the Crick strand in chromatid1
'''
if type(self.sister_chromatid1[0]) == Crick:
return 0
else:
return 1
def getCrickindex_chromatid2():
'''get the index of the Crick strand in chromatid2
'''
if type(self.sister_chromatid2[0]) == Crick:
return 0
else:
return 1
if self.phase == 'G2':
if motif == 'ccctaa':
w1 = getWatsonindex_chromatid1()
w2 = getWatsonindex_chromatid2()
return self.sister_chromatid1[w1].getCCCTAA(),self.sister_chromatid2[w2].getCCCTAA()
elif motif == 'ttaggg':
c1 = getCrickindex_chromatid1()
c2 = getCrickindex_chromatid2()
ttaggg1 = self.sister_chromatid1[c1].getTTAGGG()
ttaggg2 = self.sister_chromatid2[c2].getTTAGGG()
return ttaggg1, ttaggg2
else:
raise NameError('only on G2 chromosome')
def telomere_length(self,end = 'pter', motif = 'ccctaa'):
'''returns the telomere length (TTAGGG with motif='ttaggg' or CCCTAA with motif='ccctaa')
of a chromosome, given the location:end='pter' or end='qter'.
For a chromosome in G1 cell cycle, the length is a single number.
For a chromosome in G2, the length is a tuple, one value for each chromatid.
'''
if self.phase == 'G1':
if end == 'pter':
if motif =='ccctaa':
return self.get_pter_G1(motif)
elif motif =='ttaggg':
return self.get_pter_G1(motif)
elif end =='qter':
if motif =='ccctaa':
return self.get_qter_G1(motif)
elif motif =='ttaggg':
return self.get_qter_G1(motif)
elif self.phase =='G2':
if end == 'pter':
if motif =='ccctaa':
return self.get_pter_G2(motif)
elif motif =='ttaggg':
return self.get_pter_G2(motif)
elif end =='qter':
if motif =='ccctaa':
return self.get_qter_G2(motif)
elif motif =='ttaggg':
return self.get_qter_G2(motif)
#==============================================================================
#
# S
#
#
#==============================================================================
def test_get_pter():
k = Chromosome()
print( k)
print( 'G1+ccctaa:k.get_pter_G1() ',k.get_pter_G1())
print( "G1+ccctaa:k.get_pter_G1(motif='ccctaa') ",k.get_pter_G1(motif='ccctaa'))
print( "G1+ttaggg:k.get_pter_G1(motif='ttaggg') ",k.get_pter_G1(motif='ttaggg'))
print()
print( '----------------------')
k.set_G1_to_G2()
print( k)
print( "G2+ccctaa:k.get_pter_G1(motif='ccctaa') ",k.get_pter_G2(motif='ccctaa'))
print( "G2+ttaggg:k.get_pter_G1(motif='ttaggg') ",k.get_pter_G2(motif='ttaggg'))
print()
print()
def test_one_replication():
k = Chromosome()
#print k.chromosome
print( 'telomere p/q length G1 (ccctaa):',k.get_pter_G1(motif='ccctaa'),' ',k.get_qter_G1(motif='ccctaa'))
print( 'telomere p/q length G1 (ttaggg):',k.get_pter_G1(motif='ttaggg'),' ',k.get_qter_G1(motif='ttaggg'))
k.set_G1_to_G2()
motif='ccctaa'
print( 'ccctaa G2:','pter',k.get_pter_G2(motif),'qter',k.get_qter_G2(motif))
motif='ttaggg'
print( 'ttaggg G2:','pter',k.get_pter_G2(motif),'qter',k.get_qter_G2(motif))
print( k.chromosome)
neo = k.segregate()
print( 'neo',neo.get_pter_G1(),' ',neo.get_qter_G1())
print( 'c post seg:',k.get_pter_G1(),' ',k.get_qter_G1())
def test_replication(n):
k = Chromosome()
for i in range(n):
k.set_G1_to_G2()
k1 = k.segregate()
print( i,' ',k.get_pter_G1(),',',k.get_qter_G1(),' ',k1.get_pter_G1())
def test_rep(n):
import numpy as np
klist0 = []
k = Chromosome()
print( 'chrom name', k.name)
klist0.append(k)
generation = {}
motif = 'ttaggg'
generation[0] = (k.get_pter_G1(motif), k.get_qter_G1(motif))
for i in range(n):
klist1 = []
for c in klist0:
c.set_G1_to_G2()
for c in klist0:
klist1.append(c.segregate())
klist0 = klist0 + klist1
pq = []
for c in klist0:
pq.append((c.get_pter_G1(motif), c.get_qter_G1(motif)))
generation[i+1] = pq
# print generation.keys()
# print ((0,generation[0][0],generation[0][1]))
table = np.asarray((0,generation[0][0],generation[0][1]))
# print table.dtype
# print 'gen 0:',generation[0]
for g in generation.keys():
# print g,type(generation[g])
for pair in generation[g]:
if g == 0:
break
else:
# print 'g:',g,'pair:',pair,' ',pair[0],pair[1]
tmp = np.asarray((g,pair[0],pair[1]))
table = np.vstack([table,tmp])
return table
#==============================================================================
# Tests
#==============================================================================
if __name__ == "__main__":
test_get_pter()
test_one_replication()
telomeres=test_rep(9)
pter=telomeres[:,1]
print( pter)
qter=telomeres[:,2]
gen=telomeres[:,0]
import matplotlib.pyplot as plt
#import matplotlib.mlab as mlab
from scipy import stats
#import scipy as sc
fig = plt.figure(1)
plt.subplot(312, frameon = True)
plt.scatter(pter,qter,c=gen,s=50)
slope, intercept, r_value, p_value, slope_std_error = stats.linregress(gen, pter)
print( 'slope, intercept:',slope, intercept)
print( telomeres[gen ==4,1])
#plt.scatter(gen,pter)
plt.subplot(311, frameon = True)
# ax = fig.add_subplot(311)
# mu = sc.mean
# y = mlab.normpdf(bincenters, mu, sigma)
plt.hist(telomeres[gen==9,1], bins=100)
plt.subplot(313, frameon = True)
plt.scatter(gen, pter)
plt.show()
# -*- coding: utf-8 -*-
"""
Created on Thu Sep 13 18:25:58 2012
@author: JeanPat
"""
#from WatsonCrick import *
import ClassChromosome as K
import numpy as np
#import pdb
class Genome(object):
''' a genome is a collection of chromosomes
'''
def __init__(self, *args):
def tuplesChrom_to_dict(tu):
''' convert a tuple (('1','a'), ('1','A'), ('2','b'), ('2','B'))
into a dict {'1':('a','A'),'2':('b','B')}
'''
g={}
for c,krom in enumerate(tu):
if krom.name in g:
g[krom.name]=g[krom.name],krom
else:
g[krom.name]=krom
return g
#print type(args)
if len(args) % 2 ==0:
self.ploidy = (len(args) / 2)
else:
self.ploidy = len(args) / 2 , 1
#print('WARNING: Non diploïd genome, delta p/q will crash')
#========================================================================
# Let's populate the genome with chromosomes
#========================================================================
for count, chrom in enumerate(args):
#pdb.set_trace()
if type(chrom) != type(K.Chromosome()):
raise NameError('Genome only loves Chromosomes')
#==============================================================================
# self.genome is dictionary where :
# key= chromosome name (1, 2, 3...)
# values: pair of homologous chromosomes (a or b for ex)
#==============================================================================
self.genome = tuplesChrom_to_dict(args)
#==============================================================================
#
#Let's define what we can get from a genome object:
# * telomere length :
# -of a given chromosome/homolog
# -mean telomere length for the whole genome
# -std dev
# * difference of length:
# -between two homologs
# -distribution of telomere length
# * telomere length ratio:
# -pter / qter for a given chromosome/homolog
# -ratio distribution
# * ordered list of telomeres : ex 1pa, 2pB, 2qA, 1pA, 1qB ...
#==============================================================================
def get_chrom_phase(self, pair='1', hog='a'):
'''get if a chrom '1' homolog 'a' is G1 or G2
'''
homolog = self.get_homologous_chromosome(pair,hog)
return homolog.phase
def get_chromosomes_list(self):
return self.genome.keys()
def get_chrom_pair(self,pair='1'):
return self.genome[pair]#should be a tuple
def get_homologous_tags(self, pair='1'):
'''given a pair of chromosomes, returns the values
of Chromosome.homolog ex ['a','A']
'''
pair = self.get_chrom_pair(pair)
tags=[]
for k in pair:
tags.append(k.homolog)#k should be a Chromosome instance
#print 'tags ', tags
return tags
def get_homologous_chromosome(self,pair,hog):
'''Return one of the two chromosomes: ex
Need chromosome 1, homolog a? ask get_homologous_chromosome('1','a')
'''
pair = self.get_chrom_pair(pair)
chrom1 = pair[0]
chrom2 = pair[1]
if chrom1.homolog == hog:
return chrom1
elif chrom2.homolog == hog:
return chrom2
def get_telo_length(self, pair='1',hog='a', tel='pter',cycle='G1',motif='ccctaa'):
#==============================================================================
# Should use .homolog.phase to know if chromosome is in G1 or G2
#==============================================================================
homolog = self.get_homologous_chromosome(pair, hog)
if (tel == 'pter') and (cycle == 'G1'):
return homolog.get_pter_G1(motif)
elif tel == 'qter' and cycle == 'G1':
return homolog.get_qter_G1(motif)
elif tel == 'pter' and cycle == 'G2':
return homolog.get_pter_G2(motif)
elif tel == 'qter' and cycle == 'G2':
return homolog.get_qter_G2(motif)
else:
raise NameError('Can only get length at pter or qter in G1 or G2 cell cycle')
def get_telomere_length(self,pair='1',hog='a', tel='pter', motif='ccctaa'):
'''need not to know if G1 or G2
'''
homolog = self.get_homologous_chromosome(pair, hog)
return homolog.telomere_length(end = tel, motif = motif)
def get_mean_std_telo_lenght(self, cycle='G1',motif='ccctaa'):
'''compute the mean and standard deviation telomere length in one genome
'''
telomeres = []#an array containing all the telomeres
#print 'genome:',self.genome
for c,kpair in self.genome.items():
homolog1=kpair[0]
homolog2=kpair[1]
#==============================================================================
# Uses ccctaa motifs and chromosomes when G1 cycle is 'on'
#==============================================================================
p1=self.get_telomere_length(pair=homolog1.name, hog=homolog1.homolog,tel='pter')
q1=self.get_telomere_length(pair=homolog1.name, hog=homolog1.homolog,tel='qter')
p2=self.get_telomere_length(pair=homolog2.name, hog=homolog2.homolog,tel='pter')
q2=self.get_telomere_length(pair=homolog2.name, hog=homolog2.homolog,tel='qter')
telomeres.append(p1)
telomeres.append(q1)
telomeres.append(p2)
telomeres.append(q2)
tel = np.asarray(telomeres)
mean_telo = tel.mean()
std_telo = tel.std()
# print telomeres
# print (tel-mean_telo)/std_telo# centrée réduites
return mean_telo,std_telo
def get_pq_ratio(self,pair='1',hog='a',motif='ccctaa'):
'''Compute ratio (length pter)/(length qter) for
a given homologous chromsome
'''
p = self.get_telomere_length(pair,hog,motif,tel='pter')
q = self.get__telomere_length(pair,hog,motif,tel='qter')
if q>0:
return 1.0*p/q
else:
return None
def delta_telo(self,chromPair='1',tel='pter', cycle='G1',motif='ccctaa'):
''' calculate the difference of length between two homologous telomeres
'''
hmlog_tags = self.get_homologous_tags(chromPair)
first_hmlog = hmlog_tags[0]
second_hmlog = hmlog_tags[1]
if cycle == 'G1':
telo1 = self.get_telomere_length(chromPair, first_hmlog, tel,motif)
# print 'telo1',telo1
telo2 = self.get_telomere_length(chromPair, second_hmlog, tel,motif)
# print 'telo2',telo2
# print telo1-telo2
return telo1-telo2
elif cycle == 'G2':
pass
else:
raise NameError('only G1 or G2 cell cycle state')
def distribution_delta_telo(self, mode='raw'):
''' Should return all the difference between all the telomeres two by two
'''
pass
#==================================================
# Let's define what we can do with a genome
# * cell cycle from G1 to G2
# * segregating :1 Genome -----> 2 Genomes
#==================================================
def set_G1_to_G2(self):
for n,pair_krom in self.genome.items():
pair_krom[0].set_G1_to_G2()
pair_krom[1].set_G1_to_G2()
def G2_to_M(self):
#
chromosomes_list=[]
for n, pair_krom in self.genome.items():
rosalind = pair_krom[0].segregate()# one chromatid of one homologous chromosome
franklin = pair_krom[1].segregate()# one chromatid of the other homologous chromosome
chromosomes_list.append(rosalind)
chromosomes_list.append(franklin)
return Genome(*chromosomes_list)
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Levy *et al.* in [Telomere End-replication Problem and Cell Aging](https://www.ncbi.nlm.nih.gov/pubmed/?term=levy+M%5BAu%5D+telomere%5Bti%5D), modelized the distribution of telomeric erosion with cells divisions at a single telomere. The model accounts for the decrease in somatic cell division capabilities with in-vitro passages of fibroblasts (Hayflick's limit).\n",
"\n",
"Here, the telomere length of several chromosomes is modelised numerically with segregation of chromosomes in daughter cells. The model takes the [5' degradation of the CCCTAA strand](https://www.ncbi.nlm.nih.gov/pubmed/9054505) into account. The aim of the simulation is to compare the distributions with QFISH data.\n",
"\n",
" * The modele show that the telomere length at pter and qter are correlated.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Check the modules\n",
"The simulation relies on several modules:\n",
"\n",
" * watsoncrick \n",
" * Chromosome\n",
" * Genome\n",
" * Cell"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"........\n",
"----------------------------------------------------------------------\n",
"Ran 8 tests in 0.014s\n",
"\n",
"OK\n",
".........\n",
"----------------------------------------------------------------------\n",
"Ran 9 tests in 0.010s\n",
"\n",
"OK\n",
"........\n",
"----------------------------------------------------------------------\n",
"Ran 8 tests in 0.009s\n",
"\n",
"OK\n"
]
}
],
"source": [
"%run unittest-watsoncrick.py\n",
"%run unittest_Chromosome.py\n",
"%run unittest_Genome.py"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/home/jeanpat/Developpement/TelomereLengthSimulation/Cellular.py:116: DeprecationWarning: \n",
".ix is deprecated. Please use\n",
".loc for label based indexing or\n",
".iloc for positional indexing\n",
"\n",
"See the documentation here:\n",
"http://pandas.pydata.org/pandas-docs/stable/indexing.html#ix-indexer-is-deprecated\n",
" shortest_telo = df.ix[:, telomeres_list ].min().min()\n",
"/home/jeanpat/anaconda3/envs/DeepFish/lib/python3.6/site-packages/pandas/core/indexing.py:890: DeprecationWarning: \n",
".ix is deprecated. Please use\n",
".loc for label based indexing or\n",
".iloc for positional indexing\n",
"\n",
"See the documentation here:\n",
"http://pandas.pydata.org/pandas-docs/stable/indexing.html#ix-indexer-is-deprecated\n",
" retval = getattr(retval, self.name)._getitem_axis(key, axis=i)\n",
".....\n",
"----------------------------------------------------------------------\n",
"Ran 5 tests in 0.115s\n",
"\n",
"OK\n"
]
}
],
"source": [
"%run unittest_Cell.py"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"#import copy\n",
"#import inspect\n",
"import numpy as np\n",
"import seaborn as sb\n",
"from random import sample"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"import pandas as pn\n",
"from itertools import product"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"#%pylab inline\n",
"from matplotlib import pyplot as plt"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"import ClassChromosome as K\n",
"import Genome as G\n",
"import Cellular as C"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"# Simulate synchronous cell division:\n",
"Let's define two functions:\n",
" \n",
" * **expand_from_cell**: takes one cell and generate a cellular population after $k$ doublings (cell divisions) and finally returns a list of cells.\n",
" \n",
" * **passage**: the function takes a list of cells, chooses randomly half of the cells to make one division.\n",
" "
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"def expand_from_one_cell(cell, doubling=4):\n",
" ''' generate a cellular population by expanding one cell for N divisions\n",
" (telomerase negative cells)\n",
" '''\n",
" div = 1\n",
" mothers = []\n",
" daughters = []\n",
" mothers.append(cell)\n",
" N = doubling\n",
" while div <= N:\n",
" #print div\n",
" daughters = [c.mitose() for c in mothers if c.G0 == False]\n",
" mothers.extend(daughters)\n",
" daughters = []\n",
" div = div + 1\n",
" return mothers"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"def passage(cell_pop):\n",
" '''take randomly half the cells from the population(list of cells) and let them to divide once\n",
" to make a new cells population\n",
" '''\n",
" if len(cell_pop) > 1:\n",
" #mothers = copy.copy(random.sample(cell_pop,int(len(cell_pop)/2)))\n",
" mothers = sample(cell_pop,int(len(cell_pop)/2))\n",
" elif len(cell_pop) == 1:\n",
" #mothers = copy.copy(cell_pop)\n",
" mothers = cell_pop\n",
" daughters = [c.mitose() for c in mothers if c.G0 == False]\n",
" mothers.extend(daughters)\n",
" return mothers"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [],
"source": [
"def extract_DataFrame_from_cells(population):\n",
" a_cell = population[0]\n",
" pop_df = a_cell.genome_dataframe()\n",
" for a_cell in population[1:]:\n",
" c_df = a_cell.genome_dataframe()\n",
" pop_df = pop_df.append(c_df, ignore_index= True)\n",
" return pop_df"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [],
"source": [
"%matplotlib inline"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"## A Cell class is defined . A Cell object:\n",
" * has a genome\n",
" \n",
" * is telomerase ON/OFF\n",
" \n",
" * has a method for mitosis (returns a daughter cell)\n",
" \n",
" * count the cell divisions\n",
" \n",
" * has a method returning a pandas dataframe containing the length of its telomeres.\n",
" \n",
" * could be used to derive class for cell differenciation (telomerase ON <--> OFF, contact inhibition ...)\n",
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Generating a genome with different patterns of telomere length between homologs ##\n",
"A singled chromatid, double stranded DNA, chromosome with its telomeres can be represented by vertical bars (on the left for telomere at pter, or on the short arm and on the right at qter, or on the long chromsomal arm), an **o** for the centromere and dashed lines for the remaining chromosomal domains:\n",
"\n",
" * Pair 1 : one homolog has its two telomeres longer than those of the other homolog:\n",
" \n",
" 1m &nbsp; |||||||||||||---------o-----------|||||||||||||||||| \n",
" 1p &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |||||---------o-----------||||||||||\n",
" \n",
" * Pair 2 : length of both homologs are identical:\n",
" \n",
" 2m &nbsp; |||||||||||||-------o-------------|||||||||||||||||||||||| \n",
" 2p &nbsp; |||||||||||||-------o-------------||||||||||||||||||||||||\n",
" \n",
" * Pair 3 : Crossed pattern,one homolog has a longer and a shorter telomere:\n",
" \n",
" 3m &nbsp; |||||||||||||---------o-----------||||||||||| \n",
" 3p &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |||||---------o-----------|||||||||||||||||||||\n",
" \n",
" \n",
" * Pair 4: difference between only one pair of telomeres, at pter:\n",
" \n",
" 4m |||||||||||||----o----------------|||||||||||||||||| \n",
" 4p &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |||||----o----------------||||||||||||||||||\n",
" \n",
" \n",
" * Pair 5: difference between only one pair of telomeres, at qter:\n",
" \n",
" 5m &nbsp; |||||||||||||---o-----------------|||||||||||||||||| \n",
" 5p &nbsp; |||||||||||||---o-----------------|||||||||\n",
" \n",
" \n",
"It would be fine to automatize the initialization of a genome, that is to yield a list of telomere length. For example with a dictionnary where the name of the chromosomes (1, 2, 3 ...) as key and a 4-tuple representing the initial telomere length of each of the four telomeres of the pair of homolog chromosomes:\n",
"\n",
" {1:(p1,q1,p2,q2),2:(p1,q1,p2,q2),3:(p1,q1,p2,q2)}\n",
" \n",
"with:\n",
" \n",
" p1: telomere length (TTAGGG) at pter of the first homolog chromosome\n",
" q1: telomere length (TTAGGG) at qter of the first homolog chromosome\n",
" p2: telomere length (TTAGGG) at pter of the other homolog chromosome\n",
" \n",
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Let's play with the simulation:\n",
" * choose the initial telomere lenght distribution\n",
" * make a cell object and get its telomeres through a pandas dataframe\n",
" * then expand a cell population and makes successive passages"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [],
"source": [
"t1=(15000,18000,9000,12000)\n",
"t2=(11000, 20000, 11050,19950)\n",
"t3=(13000, 8000, 7500, 14000)\n",
"t4=(7000, 10000, 30000, 12050)\n",
"t5=(16050, 16000, 9500, 9520)\n",
"tel_distrib = {\"1\":t1, \"2\":t2,\"3\":t3,\"4\":t4,\"5\":t5}\n",
"gen0 = C.init_genome(tel_distrib)\n",
"cell0 = C.Cell(genome = gen0)"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>division</th>\n",
" <th>1pter_mat</th>\n",
" <th>1pter_pat</th>\n",
" <th>1qter_mat</th>\n",
" <th>1qter_pat</th>\n",
" <th>2pter_mat</th>\n",
" <th>2pter_pat</th>\n",
" <th>2qter_mat</th>\n",
" <th>2qter_pat</th>\n",
" <th>3pter_mat</th>\n",
" <th>...</th>\n",
" <th>3qter_mat</th>\n",
" <th>3qter_pat</th>\n",
" <th>4pter_mat</th>\n",
" <th>4pter_pat</th>\n",
" <th>4qter_mat</th>\n",
" <th>4qter_pat</th>\n",
" <th>5pter_mat</th>\n",
" <th>5pter_pat</th>\n",
" <th>5qter_mat</th>\n",
" <th>5qter_pat</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>0</td>\n",
" <td>15000</td>\n",
" <td>9000</td>\n",
" <td>18000</td>\n",
" <td>12000</td>\n",
" <td>11000</td>\n",
" <td>11050</td>\n",
" <td>20000</td>\n",
" <td>19950</td>\n",
" <td>13000</td>\n",
" <td>...</td>\n",
" <td>8000</td>\n",
" <td>14000</td>\n",
" <td>7000</td>\n",
" <td>30000</td>\n",
" <td>10000</td>\n",
" <td>12050</td>\n",
" <td>16050</td>\n",
" <td>9500</td>\n",
" <td>16000</td>\n",
" <td>9520</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>1 rows × 21 columns</p>\n",
"</div>"
],
"text/plain": [
" division 1pter_mat 1pter_pat 1qter_mat 1qter_pat 2pter_mat 2pter_pat \\\n",
"0 0 15000 9000 18000 12000 11000 11050 \n",
"\n",
" 2qter_mat 2qter_pat 3pter_mat ... 3qter_mat 3qter_pat \\\n",
"0 20000 19950 13000 ... 8000 14000 \n",
"\n",
" 4pter_mat 4pter_pat 4qter_mat 4qter_pat 5pter_mat 5pter_pat \\\n",
"0 7000 30000 10000 12050 16050 9500 \n",
"\n",
" 5qter_mat 5qter_pat \n",
"0 16000 9520 \n",
"\n",
"[1 rows x 21 columns]"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"cell0.genome_dataframe()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Making a small population from a single cell by synchronous divisions\n",
" A cell population can generated by iterative divisions from one cell. By appying $k$ divisions, the cell population has $2^{k}$ cells.\n",
"\n",
"#### After initial cell expansion or after each passage the length of the telomeres are stored in a dataframe with:\n",
"* One colum per telomere, that is four columns for two homologous chromosomes\n",
"* One line per cell"
]
},
{
"cell_type": "code",
"execution_count": 55,
"metadata": {},
"outputs": [],
"source": [
"P0 = expand_from_one_cell(cell0, doubling = 10)\n",
"df_P0 = extract_DataFrame_from_cells(P0)"
]
},
{
"cell_type": "code",
"execution_count": 56,
"metadata": {},
"outputs": [],
"source": [
"P1 = passage(P0)\n",
"df_P1 = extract_DataFrame_from_cells(P1)"
]
},
{
"cell_type": "code",
"execution_count": 57,
"metadata": {},
"outputs": [],
"source": [
"P2 = passage(P1)\n",
"df_P2 = extract_DataFrame_from_cells(P2)"
]
},
{
"cell_type": "code",
"execution_count": 58,
"metadata": {},
"outputs": [],
"source": [
"P3 = passage(P2)\n",
"df_P3 = extract_DataFrame_from_cells(P3)"
]
},
{
"cell_type": "code",
"execution_count": 59,
"metadata": {},
"outputs": [],
"source": [
"P4 = passage(P3)\n",
"df_P4 = extract_DataFrame_from_cells(P4)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### The length of the telomeres can be extracted in a pandas dataframe:\n",
" * In early passages at least, all cells should have performed the same number of divisions "
]
},
{
"cell_type": "code",
"execution_count": 60,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>division</th>\n",
" <th>1pter_mat</th>\n",
" <th>1pter_pat</th>\n",
" <th>1qter_mat</th>\n",
" <th>1qter_pat</th>\n",
" <th>2pter_mat</th>\n",
" <th>2pter_pat</th>\n",
" <th>2qter_mat</th>\n",
" <th>2qter_pat</th>\n",
" <th>3pter_mat</th>\n",
" <th>...</th>\n",
" <th>3qter_mat</th>\n",
" <th>3qter_pat</th>\n",
" <th>4pter_mat</th>\n",
" <th>4pter_pat</th>\n",
" <th>4qter_mat</th>\n",
" <th>4qter_pat</th>\n",
" <th>5pter_mat</th>\n",
" <th>5pter_pat</th>\n",
" <th>5qter_mat</th>\n",
" <th>5qter_pat</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>22</td>\n",
" <td>12824</td>\n",
" <td>6818</td>\n",
" <td>15982</td>\n",
" <td>9980</td>\n",
" <td>8854</td>\n",
" <td>9026</td>\n",
" <td>18006</td>\n",
" <td>17829</td>\n",
" <td>10880</td>\n",
" <td>...</td>\n",
" <td>5993</td>\n",
" <td>12377</td>\n",
" <td>5371</td>\n",
" <td>27464</td>\n",
" <td>7474</td>\n",
" <td>10436</td>\n",
" <td>13540</td>\n",
" <td>7678</td>\n",
" <td>14320</td>\n",
" <td>7170</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>22</td>\n",
" <td>12450</td>\n",
" <td>6043</td>\n",
" <td>16382</td>\n",
" <td>10710</td>\n",
" <td>8847</td>\n",
" <td>9215</td>\n",
" <td>18009</td>\n",
" <td>17556</td>\n",
" <td>10348</td>\n",
" <td>...</td>\n",
" <td>6533</td>\n",
" <td>12719</td>\n",
" <td>4298</td>\n",
" <td>27510</td>\n",
" <td>8571</td>\n",
" <td>10431</td>\n",
" <td>13714</td>\n",
" <td>7675</td>\n",
" <td>14174</td>\n",
" <td>7158</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>22</td>\n",
" <td>12456</td>\n",
" <td>6803</td>\n",
" <td>16362</td>\n",
" <td>10018</td>\n",
" <td>9728</td>\n",
" <td>8835</td>\n",
" <td>17157</td>\n",
" <td>17926</td>\n",
" <td>10878</td>\n",
" <td>...</td>\n",
" <td>6009</td>\n",
" <td>12533</td>\n",
" <td>5206</td>\n",
" <td>27537</td>\n",
" <td>7675</td>\n",
" <td>10435</td>\n",
" <td>13916</td>\n",
" <td>7695</td>\n",
" <td>13981</td>\n",
" <td>7180</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>22</td>\n",
" <td>12708</td>\n",
" <td>5965</td>\n",
" <td>16234</td>\n",
" <td>10882</td>\n",
" <td>8338</td>\n",
" <td>9397</td>\n",
" <td>18561</td>\n",
" <td>17396</td>\n",
" <td>11047</td>\n",
" <td>...</td>\n",
" <td>5862</td>\n",
" <td>11998</td>\n",
" <td>4998</td>\n",
" <td>28226</td>\n",
" <td>7857</td>\n",
" <td>9668</td>\n",
" <td>13869</td>\n",
" <td>7478</td>\n",
" <td>13957</td>\n",
" <td>7343</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>22</td>\n",
" <td>12881</td>\n",
" <td>6807</td>\n",
" <td>16108</td>\n",
" <td>10022</td>\n",
" <td>8330</td>\n",
" <td>8891</td>\n",
" <td>18624</td>\n",
" <td>17931</td>\n",
" <td>10158</td>\n",
" <td>...</td>\n",
" <td>6735</td>\n",
" <td>11851</td>\n",
" <td>5222</td>\n",
" <td>27866</td>\n",
" <td>7638</td>\n",
" <td>10050</td>\n",
" <td>13345</td>\n",
" <td>7542</td>\n",
" <td>14515</td>\n",
" <td>7376</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>5 rows × 21 columns</p>\n",
"</div>"
],
"text/plain": [
" division 1pter_mat 1pter_pat 1qter_mat 1qter_pat 2pter_mat 2pter_pat \\\n",
"0 22 12824 6818 15982 9980 8854 9026 \n",
"1 22 12450 6043 16382 10710 8847 9215 \n",
"2 22 12456 6803 16362 10018 9728 8835 \n",
"3 22 12708 5965 16234 10882 8338 9397 \n",
"4 22 12881 6807 16108 10022 8330 8891 \n",
"\n",
" 2qter_mat 2qter_pat 3pter_mat ... 3qter_mat 3qter_pat \\\n",
"0 18006 17829 10880 ... 5993 12377 \n",
"1 18009 17556 10348 ... 6533 12719 \n",
"2 17157 17926 10878 ... 6009 12533 \n",
"3 18561 17396 11047 ... 5862 11998 \n",
"4 18624 17931 10158 ... 6735 11851 \n",
"\n",
" 4pter_mat 4pter_pat 4qter_mat 4qter_pat 5pter_mat 5pter_pat \\\n",
"0 5371 27464 7474 10436 13540 7678 \n",
"1 4298 27510 8571 10431 13714 7675 \n",
"2 5206 27537 7675 10435 13916 7695 \n",
"3 4998 28226 7857 9668 13869 7478 \n",
"4 5222 27866 7638 10050 13345 7542 \n",
"\n",
" 5qter_mat 5qter_pat \n",
"0 14320 7170 \n",
"1 14174 7158 \n",
"2 13981 7180 \n",
"3 13957 7343 \n",
"4 14515 7376 \n",
"\n",
"[5 rows x 21 columns]"
]
},
"execution_count": 60,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df_P4.head()"
]
},
{
"cell_type": "code",
"execution_count": 61,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"11350.65"
]
},
"execution_count": 61,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df_P4.iloc[0,1:].mean()"
]
},
{
"cell_type": "code",
"execution_count": 75,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>division</th>\n",
" <th>1pter_mat</th>\n",
" <th>1pter_pat</th>\n",
" <th>1qter_mat</th>\n",
" <th>1qter_pat</th>\n",
" <th>2pter_mat</th>\n",
" <th>2pter_pat</th>\n",
" <th>2qter_mat</th>\n",
" <th>2qter_pat</th>\n",
" <th>3pter_mat</th>\n",
" <th>...</th>\n",
" <th>3qter_mat</th>\n",
" <th>3qter_pat</th>\n",
" <th>4pter_mat</th>\n",
" <th>4pter_pat</th>\n",
" <th>4qter_mat</th>\n",
" <th>4qter_pat</th>\n",
" <th>5pter_mat</th>\n",
" <th>5pter_pat</th>\n",
" <th>5qter_mat</th>\n",
" <th>5qter_pat</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>18</td>\n",
" <td>13203</td>\n",
" <td>6852</td>\n",
" <td>16422</td>\n",
" <td>10718</td>\n",
" <td>9064</td>\n",
" <td>9767</td>\n",
" <td>18582</td>\n",
" <td>17768</td>\n",
" <td>11585</td>\n",
" <td>...</td>\n",
" <td>6000</td>\n",
" <td>12372</td>\n",
" <td>5407</td>\n",
" <td>28431</td>\n",
" <td>8202</td>\n",
" <td>10199</td>\n",
" <td>14433</td>\n",
" <td>8039</td>\n",
" <td>14134</td>\n",
" <td>7516</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>18</td>\n",
" <td>13197</td>\n",
" <td>7186</td>\n",
" <td>16344</td>\n",
" <td>10377</td>\n",
" <td>8814</td>\n",
" <td>9398</td>\n",
" <td>18782</td>\n",
" <td>18126</td>\n",
" <td>10865</td>\n",
" <td>...</td>\n",
" <td>6736</td>\n",
" <td>12556</td>\n",
" <td>5534</td>\n",
" <td>28207</td>\n",
" <td>8033</td>\n",
" <td>10390</td>\n",
" <td>14069</td>\n",
" <td>8218</td>\n",
" <td>14511</td>\n",
" <td>7351</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>18</td>\n",
" <td>12846</td>\n",
" <td>7000</td>\n",
" <td>16746</td>\n",
" <td>10510</td>\n",
" <td>8443</td>\n",
" <td>9251</td>\n",
" <td>19106</td>\n",
" <td>18299</td>\n",
" <td>11384</td>\n",
" <td>...</td>\n",
" <td>6194</td>\n",
" <td>12568</td>\n",
" <td>5706</td>\n",
" <td>28406</td>\n",
" <td>7839</td>\n",
" <td>10261</td>\n",
" <td>14423</td>\n",
" <td>8221</td>\n",
" <td>14127</td>\n",
" <td>7337</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>18</td>\n",
" <td>12827</td>\n",
" <td>7728</td>\n",
" <td>16753</td>\n",
" <td>9834</td>\n",
" <td>8703</td>\n",
" <td>9423</td>\n",
" <td>18910</td>\n",
" <td>18163</td>\n",
" <td>11374</td>\n",
" <td>...</td>\n",
" <td>6193</td>\n",
" <td>12732</td>\n",
" <td>5388</td>\n",
" <td>28048</td>\n",
" <td>8182</td>\n",
" <td>10588</td>\n",
" <td>14617</td>\n",
" <td>8046</td>\n",
" <td>13990</td>\n",
" <td>7570</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>18</td>\n",
" <td>13175</td>\n",
" <td>6807</td>\n",
" <td>16382</td>\n",
" <td>10727</td>\n",
" <td>8295</td>\n",
" <td>9453</td>\n",
" <td>19314</td>\n",
" <td>18155</td>\n",
" <td>10810</td>\n",
" <td>...</td>\n",
" <td>6745</td>\n",
" <td>12043</td>\n",
" <td>5313</td>\n",
" <td>28215</td>\n",
" <td>8235</td>\n",
" <td>10419</td>\n",
" <td>14195</td>\n",
" <td>7337</td>\n",
" <td>14324</td>\n",
" <td>8243</td>\n",
" </tr>\n",
" <tr>\n",
" <th>5</th>\n",
" <td>18</td>\n",
" <td>13047</td>\n",
" <td>7368</td>\n",
" <td>16513</td>\n",
" <td>10149</td>\n",
" <td>9565</td>\n",
" <td>9411</td>\n",
" <td>18033</td>\n",
" <td>18106</td>\n",
" <td>11386</td>\n",
" <td>...</td>\n",
" <td>6162</td>\n",
" <td>12553</td>\n",
" <td>5352</td>\n",
" <td>27973</td>\n",
" <td>8194</td>\n",
" <td>10590</td>\n",
" <td>14069</td>\n",
" <td>8231</td>\n",
" <td>14565</td>\n",
" <td>7357</td>\n",
" </tr>\n",
" <tr>\n",
" <th>6</th>\n",
" <td>18</td>\n",
" <td>12640</td>\n",
" <td>7580</td>\n",
" <td>16927</td>\n",
" <td>10037</td>\n",
" <td>9037</td>\n",
" <td>9379</td>\n",
" <td>18537</td>\n",
" <td>18115</td>\n",
" <td>11550</td>\n",
" <td>...</td>\n",
" <td>6046</td>\n",
" <td>12720</td>\n",
" <td>5573</td>\n",
" <td>28246</td>\n",
" <td>8014</td>\n",
" <td>10416</td>\n",
" <td>14452</td>\n",
" <td>7878</td>\n",
" <td>14180</td>\n",
" <td>7681</td>\n",
" </tr>\n",
" <tr>\n",
" <th>7</th>\n",
" <td>18</td>\n",
" <td>13215</td>\n",
" <td>7399</td>\n",
" <td>16347</td>\n",
" <td>10188</td>\n",
" <td>8885</td>\n",
" <td>9379</td>\n",
" <td>18749</td>\n",
" <td>18122</td>\n",
" <td>10863</td>\n",
" <td>...</td>\n",
" <td>6742</td>\n",
" <td>12557</td>\n",
" <td>5343</td>\n",
" <td>27842</td>\n",
" <td>8198</td>\n",
" <td>10747</td>\n",
" <td>14258</td>\n",
" <td>8043</td>\n",
" <td>14341</td>\n",
" <td>7560</td>\n",
" </tr>\n",
" <tr>\n",
" <th>8</th>\n",
" <td>18</td>\n",
" <td>12995</td>\n",
" <td>6674</td>\n",
" <td>16617</td>\n",
" <td>10883</td>\n",
" <td>8637</td>\n",
" <td>9771</td>\n",
" <td>18932</td>\n",
" <td>17783</td>\n",
" <td>11232</td>\n",
" <td>...</td>\n",
" <td>6367</td>\n",
" <td>12914</td>\n",
" <td>5226</td>\n",
" <td>28773</td>\n",
" <td>8391</td>\n",
" <td>9838</td>\n",
" <td>13907</td>\n",
" <td>7473</td>\n",
" <td>14722</td>\n",
" <td>8073</td>\n",
" </tr>\n",
" <tr>\n",
" <th>9</th>\n",
" <td>18</td>\n",
" <td>13741</td>\n",
" <td>7360</td>\n",
" <td>15834</td>\n",
" <td>10196</td>\n",
" <td>8694</td>\n",
" <td>9414</td>\n",
" <td>18936</td>\n",
" <td>18102</td>\n",
" <td>11026</td>\n",
" <td>...</td>\n",
" <td>6550</td>\n",
" <td>12685</td>\n",
" <td>5199</td>\n",
" <td>28549</td>\n",
" <td>8412</td>\n",
" <td>10020</td>\n",
" <td>14272</td>\n",
" <td>8225</td>\n",
" <td>14347</td>\n",
" <td>7358</td>\n",
" </tr>\n",
" <tr>\n",
" <th>10</th>\n",
" <td>18</td>\n",
" <td>13166</td>\n",
" <td>7034</td>\n",
" <td>16355</td>\n",
" <td>10543</td>\n",
" <td>8859</td>\n",
" <td>9798</td>\n",
" <td>18771</td>\n",
" <td>17788</td>\n",
" <td>11006</td>\n",
" <td>...</td>\n",
" <td>6566</td>\n",
" <td>12757</td>\n",
" <td>5514</td>\n",
" <td>28230</td>\n",
" <td>8028</td>\n",
" <td>10410</td>\n",
" <td>14774</td>\n",
" <td>7683</td>\n",
" <td>13803</td>\n",
" <td>7900</td>\n",
" </tr>\n",
" <tr>\n",
" <th>11</th>\n",
" <td>18</td>\n",
" <td>12629</td>\n",
" <td>7037</td>\n",
" <td>16900</td>\n",
" <td>10532</td>\n",
" <td>9041</td>\n",
" <td>8858</td>\n",
" <td>18585</td>\n",
" <td>18686</td>\n",
" <td>11222</td>\n",
" <td>...</td>\n",
" <td>6368</td>\n",
" <td>11984</td>\n",
" <td>5718</td>\n",
" <td>27833</td>\n",
" <td>7810</td>\n",
" <td>10771</td>\n",
" <td>14222</td>\n",
" <td>8246</td>\n",
" <td>14352</td>\n",
" <td>7330</td>\n",
" </tr>\n",
" <tr>\n",
" <th>12</th>\n",
" <td>18</td>\n",
" <td>12824</td>\n",
" <td>6643</td>\n",
" <td>16737</td>\n",
" <td>10903</td>\n",
" <td>9016</td>\n",
" <td>9777</td>\n",
" <td>18593</td>\n",
" <td>17747</td>\n",
" <td>11407</td>\n",
" <td>...</td>\n",
" <td>6214</td>\n",
" <td>12045</td>\n",
" <td>5561</td>\n",
" <td>28204</td>\n",
" <td>8029</td>\n",
" <td>10413</td>\n",
" <td>14231</td>\n",
" <td>7689</td>\n",
" <td>14357</td>\n",
" <td>7879</td>\n",
" </tr>\n",
" <tr>\n",
" <th>13</th>\n",
" <td>18</td>\n",
" <td>13189</td>\n",
" <td>7040</td>\n",
" <td>16353</td>\n",
" <td>10519</td>\n",
" <td>9417</td>\n",
" <td>9016</td>\n",
" <td>18201</td>\n",
" <td>18459</td>\n",
" <td>11210</td>\n",
" <td>...</td>\n",
" <td>6337</td>\n",
" <td>12730</td>\n",
" <td>5378</td>\n",
" <td>27858</td>\n",
" <td>8221</td>\n",
" <td>10752</td>\n",
" <td>14054</td>\n",
" <td>7893</td>\n",
" <td>14499</td>\n",
" <td>7733</td>\n",
" </tr>\n",
" <tr>\n",
" <th>14</th>\n",
" <td>18</td>\n",
" <td>12963</td>\n",
" <td>7027</td>\n",
" <td>16627</td>\n",
" <td>10550</td>\n",
" <td>8814</td>\n",
" <td>9584</td>\n",
" <td>18777</td>\n",
" <td>17943</td>\n",
" <td>11394</td>\n",
" <td>...</td>\n",
" <td>6206</td>\n",
" <td>12372</td>\n",
" <td>4850</td>\n",
" <td>28044</td>\n",
" <td>8738</td>\n",
" <td>10582</td>\n",
" <td>14435</td>\n",
" <td>8051</td>\n",
" <td>14178</td>\n",
" <td>7557</td>\n",
" </tr>\n",
" <tr>\n",
" <th>15</th>\n",
" <td>18</td>\n",
" <td>13030</td>\n",
" <td>7203</td>\n",
" <td>16538</td>\n",
" <td>10350</td>\n",
" <td>8854</td>\n",
" <td>9194</td>\n",
" <td>18775</td>\n",
" <td>18313</td>\n",
" <td>11555</td>\n",
" <td>...</td>\n",
" <td>6040</td>\n",
" <td>12174</td>\n",
" <td>5382</td>\n",
" <td>28012</td>\n",
" <td>8226</td>\n",
" <td>10592</td>\n",
" <td>14428</td>\n",
" <td>8387</td>\n",
" <td>14176</td>\n",
" <td>7210</td>\n",
" </tr>\n",
" <tr>\n",
" <th>16</th>\n",
" <td>18</td>\n",
" <td>13050</td>\n",
" <td>7363</td>\n",
" <td>16587</td>\n",
" <td>10195</td>\n",
" <td>9187</td>\n",
" <td>9198</td>\n",
" <td>18411</td>\n",
" <td>18324</td>\n",
" <td>11065</td>\n",
" <td>...</td>\n",
" <td>6554</td>\n",
" <td>12356</td>\n",
" <td>5577</td>\n",
" <td>28047</td>\n",
" <td>8010</td>\n",
" <td>10604</td>\n",
" <td>14053</td>\n",
" <td>7692</td>\n",
" <td>14531</td>\n",
" <td>7878</td>\n",
" </tr>\n",
" <tr>\n",
" <th>17</th>\n",
" <td>18</td>\n",
" <td>13000</td>\n",
" <td>7588</td>\n",
" <td>16553</td>\n",
" <td>10036</td>\n",
" <td>9030</td>\n",
" <td>9183</td>\n",
" <td>18608</td>\n",
" <td>18315</td>\n",
" <td>10489</td>\n",
" <td>...</td>\n",
" <td>7104</td>\n",
" <td>12890</td>\n",
" <td>5375</td>\n",
" <td>28203</td>\n",
" <td>8275</td>\n",
" <td>10356</td>\n",
" <td>14619</td>\n",
" <td>8402</td>\n",
" <td>13980</td>\n",
" <td>7179</td>\n",
" </tr>\n",
" <tr>\n",
" <th>18</th>\n",
" <td>18</td>\n",
" <td>13002</td>\n",
" <td>7225</td>\n",
" <td>16562</td>\n",
" <td>10371</td>\n",
" <td>9037</td>\n",
" <td>9075</td>\n",
" <td>18585</td>\n",
" <td>18464</td>\n",
" <td>11394</td>\n",
" <td>...</td>\n",
" <td>6197</td>\n",
" <td>12560</td>\n",
" <td>5532</td>\n",
" <td>28384</td>\n",
" <td>7987</td>\n",
" <td>10232</td>\n",
" <td>14269</td>\n",
" <td>7684</td>\n",
" <td>14329</td>\n",
" <td>7890</td>\n",
" </tr>\n",
" <tr>\n",
" <th>19</th>\n",
" <td>18</td>\n",
" <td>12963</td>\n",
" <td>7573</td>\n",
" <td>16532</td>\n",
" <td>10023</td>\n",
" <td>9054</td>\n",
" <td>8833</td>\n",
" <td>18579</td>\n",
" <td>18686</td>\n",
" <td>11567</td>\n",
" <td>...</td>\n",
" <td>6030</td>\n",
" <td>12208</td>\n",
" <td>5543</td>\n",
" <td>27508</td>\n",
" <td>8019</td>\n",
" <td>11125</td>\n",
" <td>14424</td>\n",
" <td>7673</td>\n",
" <td>14177</td>\n",
" <td>7879</td>\n",
" </tr>\n",
" <tr>\n",
" <th>20</th>\n",
" <td>18</td>\n",
" <td>13366</td>\n",
" <td>7001</td>\n",
" <td>16229</td>\n",
" <td>10557</td>\n",
" <td>8465</td>\n",
" <td>9606</td>\n",
" <td>19105</td>\n",
" <td>17977</td>\n",
" <td>10888</td>\n",
" <td>...</td>\n",
" <td>6735</td>\n",
" <td>12055</td>\n",
" <td>6080</td>\n",
" <td>28035</td>\n",
" <td>7495</td>\n",
" <td>10579</td>\n",
" <td>13885</td>\n",
" <td>7868</td>\n",
" <td>14691</td>\n",
" <td>7709</td>\n",
" </tr>\n",
" <tr>\n",
" <th>21</th>\n",
" <td>18</td>\n",
" <td>12993</td>\n",
" <td>7051</td>\n",
" <td>16516</td>\n",
" <td>10527</td>\n",
" <td>9564</td>\n",
" <td>9410</td>\n",
" <td>18034</td>\n",
" <td>18136</td>\n",
" <td>10860</td>\n",
" <td>...</td>\n",
" <td>6751</td>\n",
" <td>12901</td>\n",
" <td>5550</td>\n",
" <td>28351</td>\n",
" <td>8060</td>\n",
" <td>10187</td>\n",
" <td>13853</td>\n",
" <td>8234</td>\n",
" <td>14715</td>\n",
" <td>7330</td>\n",
" </tr>\n",
" <tr>\n",
" <th>22</th>\n",
" <td>18</td>\n",
" <td>12822</td>\n",
" <td>7727</td>\n",
" <td>16760</td>\n",
" <td>9792</td>\n",
" <td>8971</td>\n",
" <td>9759</td>\n",
" <td>18562</td>\n",
" <td>17758</td>\n",
" <td>11579</td>\n",
" <td>...</td>\n",
" <td>6008</td>\n",
" <td>12919</td>\n",
" <td>5399</td>\n",
" <td>28067</td>\n",
" <td>8217</td>\n",
" <td>10573</td>\n",
" <td>14249</td>\n",
" <td>8243</td>\n",
" <td>14383</td>\n",
" <td>7386</td>\n",
" </tr>\n",
" <tr>\n",
" <th>23</th>\n",
" <td>18</td>\n",
" <td>12473</td>\n",
" <td>7190</td>\n",
" <td>17104</td>\n",
" <td>10357</td>\n",
" <td>8689</td>\n",
" <td>9761</td>\n",
" <td>18942</td>\n",
" <td>17751</td>\n",
" <td>11254</td>\n",
" <td>...</td>\n",
" <td>6381</td>\n",
" <td>12533</td>\n",
" <td>5014</td>\n",
" <td>27651</td>\n",
" <td>8588</td>\n",
" <td>10923</td>\n",
" <td>14029</td>\n",
" <td>7857</td>\n",
" <td>14543</td>\n",
" <td>7721</td>\n",
" </tr>\n",
" <tr>\n",
" <th>24</th>\n",
" <td>18</td>\n",
" <td>12651</td>\n",
" <td>6817</td>\n",
" <td>16913</td>\n",
" <td>10713</td>\n",
" <td>8644</td>\n",
" <td>10125</td>\n",
" <td>18929</td>\n",
" <td>17415</td>\n",
" <td>11403</td>\n",
" <td>...</td>\n",
" <td>6221</td>\n",
" <td>12213</td>\n",
" <td>5759</td>\n",
" <td>28405</td>\n",
" <td>7847</td>\n",
" <td>10235</td>\n",
" <td>14212</td>\n",
" <td>7684</td>\n",
" <td>14353</td>\n",
" <td>7936</td>\n",
" </tr>\n",
" <tr>\n",
" <th>25</th>\n",
" <td>18</td>\n",
" <td>13352</td>\n",
" <td>7549</td>\n",
" <td>16167</td>\n",
" <td>10001</td>\n",
" <td>9241</td>\n",
" <td>9421</td>\n",
" <td>18401</td>\n",
" <td>18142</td>\n",
" <td>10889</td>\n",
" <td>...</td>\n",
" <td>6748</td>\n",
" <td>12919</td>\n",
" <td>4606</td>\n",
" <td>28403</td>\n",
" <td>8904</td>\n",
" <td>10209</td>\n",
" <td>14236</td>\n",
" <td>8542</td>\n",
" <td>14340</td>\n",
" <td>6973</td>\n",
" </tr>\n",
" <tr>\n",
" <th>26</th>\n",
" <td>18</td>\n",
" <td>13166</td>\n",
" <td>7044</td>\n",
" <td>16358</td>\n",
" <td>10505</td>\n",
" <td>8864</td>\n",
" <td>9223</td>\n",
" <td>18760</td>\n",
" <td>18344</td>\n",
" <td>11202</td>\n",
" <td>...</td>\n",
" <td>6374</td>\n",
" <td>12735</td>\n",
" <td>5220</td>\n",
" <td>28613</td>\n",
" <td>8385</td>\n",
" <td>10052</td>\n",
" <td>14783</td>\n",
" <td>8036</td>\n",
" <td>13808</td>\n",
" <td>7528</td>\n",
" </tr>\n",
" <tr>\n",
" <th>27</th>\n",
" <td>18</td>\n",
" <td>13194</td>\n",
" <td>7597</td>\n",
" <td>16367</td>\n",
" <td>9949</td>\n",
" <td>9049</td>\n",
" <td>9214</td>\n",
" <td>18564</td>\n",
" <td>18312</td>\n",
" <td>11399</td>\n",
" <td>...</td>\n",
" <td>6222</td>\n",
" <td>12174</td>\n",
" <td>5401</td>\n",
" <td>27646</td>\n",
" <td>8200</td>\n",
" <td>10951</td>\n",
" <td>14078</td>\n",
" <td>7694</td>\n",
" <td>14522</td>\n",
" <td>7894</td>\n",
" </tr>\n",
" <tr>\n",
" <th>28</th>\n",
" <td>18</td>\n",
" <td>13384</td>\n",
" <td>7193</td>\n",
" <td>16226</td>\n",
" <td>10403</td>\n",
" <td>8675</td>\n",
" <td>9406</td>\n",
" <td>18959</td>\n",
" <td>18140</td>\n",
" <td>11578</td>\n",
" <td>...</td>\n",
" <td>6003</td>\n",
" <td>12386</td>\n",
" <td>5580</td>\n",
" <td>28359</td>\n",
" <td>8042</td>\n",
" <td>10247</td>\n",
" <td>14603</td>\n",
" <td>7678</td>\n",
" <td>14013</td>\n",
" <td>7890</td>\n",
" </tr>\n",
" <tr>\n",
" <th>29</th>\n",
" <td>18</td>\n",
" <td>13007</td>\n",
" <td>7170</td>\n",
" <td>16556</td>\n",
" <td>10361</td>\n",
" <td>9389</td>\n",
" <td>9621</td>\n",
" <td>18243</td>\n",
" <td>17936</td>\n",
" <td>11592</td>\n",
" <td>...</td>\n",
" <td>6010</td>\n",
" <td>12546</td>\n",
" <td>5246</td>\n",
" <td>28060</td>\n",
" <td>8373</td>\n",
" <td>10569</td>\n",
" <td>14058</td>\n",
" <td>8621</td>\n",
" <td>14532</td>\n",
" <td>7001</td>\n",
" </tr>\n",
" <tr>\n",
" <th>...</th>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>994</th>\n",
" <td>18</td>\n",
" <td>12836</td>\n",
" <td>7012</td>\n",
" <td>16726</td>\n",
" <td>10517</td>\n",
" <td>8491</td>\n",
" <td>9624</td>\n",
" <td>19110</td>\n",
" <td>17918</td>\n",
" <td>11593</td>\n",
" <td>...</td>\n",
" <td>6023</td>\n",
" <td>12743</td>\n",
" <td>5145</td>\n",
" <td>28437</td>\n",
" <td>8329</td>\n",
" <td>10267</td>\n",
" <td>14787</td>\n",
" <td>7683</td>\n",
" <td>13782</td>\n",
" <td>7890</td>\n",
" </tr>\n",
" <tr>\n",
" <th>995</th>\n",
" <td>18</td>\n",
" <td>13196</td>\n",
" <td>7345</td>\n",
" <td>16357</td>\n",
" <td>10171</td>\n",
" <td>8797</td>\n",
" <td>9058</td>\n",
" <td>18762</td>\n",
" <td>18492</td>\n",
" <td>11423</td>\n",
" <td>...</td>\n",
" <td>6211</td>\n",
" <td>12920</td>\n",
" <td>5577</td>\n",
" <td>28359</td>\n",
" <td>8007</td>\n",
" <td>10248</td>\n",
" <td>14615</td>\n",
" <td>8058</td>\n",
" <td>13950</td>\n",
" <td>7508</td>\n",
" </tr>\n",
" <tr>\n",
" <th>996</th>\n",
" <td>18</td>\n",
" <td>12843</td>\n",
" <td>7215</td>\n",
" <td>16759</td>\n",
" <td>10366</td>\n",
" <td>8851</td>\n",
" <td>9248</td>\n",
" <td>18757</td>\n",
" <td>18309</td>\n",
" <td>11109</td>\n",
" <td>...</td>\n",
" <td>6549</td>\n",
" <td>12539</td>\n",
" <td>5353</td>\n",
" <td>28602</td>\n",
" <td>8223</td>\n",
" <td>10080</td>\n",
" <td>13995</td>\n",
" <td>8029</td>\n",
" <td>14504</td>\n",
" <td>7517</td>\n",
" </tr>\n",
" <tr>\n",
" <th>997</th>\n",
" <td>18</td>\n",
" <td>12861</td>\n",
" <td>7368</td>\n",
" <td>16710</td>\n",
" <td>10192</td>\n",
" <td>8839</td>\n",
" <td>9790</td>\n",
" <td>18733</td>\n",
" <td>17727</td>\n",
" <td>11073</td>\n",
" <td>...</td>\n",
" <td>6531</td>\n",
" <td>12347</td>\n",
" <td>5379</td>\n",
" <td>28009</td>\n",
" <td>8217</td>\n",
" <td>10598</td>\n",
" <td>13707</td>\n",
" <td>8068</td>\n",