comparison aggregate.py @ 12:04ee1373b7e7 draft

Uploaded
author kaymccoy
date Fri, 12 Aug 2016 22:49:34 -0400
parents
children
comparison
equal deleted inserted replaced
11:bc071a8fbb04 12:04ee1373b7e7
1 # A translation of aggregate.pl into python! For analysis of Tn-Seq.
2 # This script requires BioPython just like calc_fitness.py, so you need it installed along with its dependencies if you want to run these scripts on your own.
3 # How to install BioPython and a list of its dependencies can be found here: http://biopython.org/DIST/docs/install/Installation.html
4 # K. McCoy
5
6
7
8
9
10
11
12
13
14 ##### ARGUMENTS #####
15
16 def print_usage():
17 print "Aggregate.py's usage is as follows:" + "\n\n"
18 print "\033[1m" + "Required" + "\033[0m" + "\n"
19 print "-o" + "\t\t" + "Output file for aggregated data." + "\n"
20 print "\n"
21 print "\033[1m" + "Optional" + "\033[0m" + "\n"
22 print "-c" + "\t\t" + "Check for missing genes in the data set - provide a reference genome in genbank format. Missing genes will be sent to stdout." + "\n"
23 print "-m" + "\t\t" + "Place a mark in an extra column for this set of genes. Provide a file with a list of genes seperated by newlines." + "\n"
24 print "-x" + "\t\t" + "Cutoff: Don't include fitness scores with average counts (c1+c2)/2 < x (default: 0)" + "\n"
25 print "-b" + "\t\t" + "Blanks: Exclude -b % of blank fitness scores (scores where c2 = 0) (default: 0 = 0%)" + "\n"
26 print "-f" + "\t\t" + "An in-between file carrying information on the blank count found from calc_fitness or consol_fitness; one of two ways to pass a blank count to this script" + "\n"
27 print "-w" + "\t\t" + "Use weighted algorithm to calculate averages, variance, sd, se" + "\n"
28 print "-l" + "\t\t" + "Weight ceiling: maximum value to use as a weight (default: 999,999)" + "\n"
29 print "\n"
30 print "All remainder arguements will be treated as fitness files (those files created by calc_fitness.py)" + "\n"
31 print "\n"
32
33 import argparse
34 parser = argparse.ArgumentParser()
35 parser.add_argument("-o", action="store", dest="summary")
36 parser.add_argument("-c", action="store", dest="find_missing")
37 parser.add_argument("-m", action="store", dest="marked")
38 parser.add_argument("-x", action="store", dest="cutoff")
39 parser.add_argument("-b", action="store", dest="blank_pc")
40 parser.add_argument("-f", action="store", dest="blank_file")
41 parser.add_argument("-w", action="store", dest="weighted")
42 parser.add_argument("-l", action="store", dest="weight_ceiling")
43 parser.add_argument("fitnessfiles", nargs=argparse.REMAINDER)
44
45 arguments = parser.parse_args()
46
47 if not arguments.summary:
48 print "\n" + "You are missing a value for the -o flag. "
49 print_usage()
50 quit()
51
52 if not arguments.fitnessfiles:
53 print "\n" + "You are missing fitness file(s); these should be entered immediately after all the flags. "
54 print_usage()
55 quit()
56
57 # 999,999 is a trivial placeholder number
58
59 if (not arguments.weight_ceiling):
60 arguments.weight_ceiling = 999999
61
62 # Cutoff exists to discard positions with a low number of counted transcripts, because their fitness may not be as accurate - for the same reasoning that studies with low sample sizes can be innacurate.
63
64 if (not arguments.cutoff):
65 arguments.cutoff = 0
66
67 # Gets information from the txt output file of calc_fit / consol, if inputted
68
69 if arguments.blank_file:
70 with open(arguments.blank_file) as file:
71 blank_pc = file.read().splitlines()
72 arguments.blank_pc = float(blank_pc[0].split()[1])
73
74 if (not arguments.blank_pc):
75 arguments.blank_pc = 0
76
77
78
79
80
81 ##### SUBROUTINES #####
82
83 # A subroutine that calculates the average, variance, standard deviation (sd), and standard error (se) of a group of scores; for use when aggregating scores by gene later on
84
85 import math
86 def average(scores):
87 sum = 0
88 num = 0
89 for i in scores:
90 ###!!!
91 print i
92 sum += i
93 num += 1
94 average = sum/num
95 xminusxbars = 0
96 for i in scores:
97 xminusxbars += (i - average)**2
98 variance = xminusxbars/(num-1)
99 sd = math.sqrt(variance)
100 se = sd / math.sqrt(num)
101 return (average, variance, sd, se)
102
103 # A subroutine that calculates the weighted average, variance, standard deviation (sd), and standard error (se) of a group of scores; the weights come from the number of reads each insertion location has
104 # For use when aggregating scores by gene later on, if the weighted argument is called
105
106 def weighted_average(scores,weights):
107 sum = 0
108 weighted_average = 0
109 weighted_variance = 0
110 top = 0
111 bottom = 0
112 i = 0
113 while i < len(weights):
114 if not scores[i]:
115 scores[i] = 0.0
116 top += float(weights[i])*float(scores[i])
117 bottom += float(weights[i])
118 i += 1
119 if bottom == 0:
120 return 0
121 weighted_average = top/bottom
122 top = 0
123 bottom = 0
124 i = 0
125 while i < len(weights):
126 top += float(weights[i]) * (float(scores[i]) - weighted_average)**2
127 bottom += float(weights[i])
128 i += 1
129 weighted_variance = top/bottom
130 weighted_stdev = math.sqrt(weighted_variance)
131 weighted_stder = weighted_stdev/math.sqrt(len(scores))
132 return (weighted_average, weighted_variance, weighted_stdev, weighted_stder)
133
134
135
136
137
138
139
140
141
142
143 ##### AGGREGATION / CALCULATIONS #####
144
145 #Reads the genes which should be marked in the final aggregate file into an array
146
147 import os.path
148 if arguments.marked:
149 with open(arguments.marked) as file:
150 marked_set = file.read().splitlines()
151
152 #Creates a dictionary of dictionaries to contain a summary of all genes and their fitness values
153 #The fitness values and weights match up, so that the weight of gene_summary[locus]["w"][2] would be gene_summary[locus]["s"][2]
154
155 import csv
156 gene_summary = {}
157 for eachfile in arguments.fitnessfiles:
158 with open(eachfile) as csvfile:
159 lines = csv.reader(csvfile)
160 for line in lines:
161 locus = line[9]
162 w = line[12]
163 if w == 'nW':
164 continue
165 if not w:
166 w == 0
167 c1 = float(line[2])
168 c2 = float(line[3])
169 avg = (c1+c2)/2
170 if avg < float(arguments.cutoff):
171 continue
172 if avg > float(arguments.weight_ceiling):
173 avg = arguments.weight_ceiling
174 if locus not in gene_summary:
175 gene_summary[locus] = {"w" : [], "s": []}
176 gene_summary[locus]["w"].append(w)
177 gene_summary[locus]["s"].append(avg)
178
179 #If finding any missing gene loci is requested in the arguments, starts out by loading all the known features from a genbank file
180
181 from Bio import SeqIO
182 if (arguments.find_missing):
183 output = [["locus","mean","var","sd","se","gene","Total","Blank","Not Blank","Blank Removed","M\n"]]
184 handle = open(arguments.find_missing, "rU")
185 for record in SeqIO.parse(handle, "genbank"):
186 refname = record.id
187 features = record.features
188 handle.close()
189
190 #Goes through the features to find which are genes
191
192 for feature in features:
193 gene = ""
194 if feature.type == "gene":
195 locus = "".join(feature.qualifiers["locus_tag"])
196 if "gene" in feature.qualifiers:
197 gene = "".join(feature.qualifiers["gene"])
198 else:
199 continue
200
201 #Goes through the fitness scores of insertions within each gene, and removes whatever % of blank fitness scores were requested along with their corresponding weights
202
203 #!!! issue = locus["w"] returning str not float for some reason!
204
205 sum = 0
206 num = 0
207 avgsum = 0
208 blank_ws = 0
209 i = 0
210 if locus in gene_summary.keys():
211 for w in gene_summary[locus]["w"]:
212 if float(w) == 0:
213 blank_ws += 1
214 else:
215 sum += float(w)
216 num += 1
217 count = num + blank_ws
218 removed = 0
219 to_remove = int(float(arguments.blank_pc)*count)
220 if blank_ws > 0:
221 i = 0
222 while i < len(gene_summary[locus]["w"]):
223 w = gene_summary[locus]["w"][i]
224 if removed == to_remove:
225 break
226 if float(w) == 0:
227 del gene_summary[locus]["w"][i]
228 del gene_summary[locus]["s"][i]
229 removed += 1
230 i -= 1
231 i += 1
232
233 #If all the fitness values within a gene are empty, sets mean/var to 0.10 and Xs out sd/se; marks the gene if that's requested
234
235 if num == 0:
236 if (arguments.marked and locus in marked_set):
237 output.append([locus, "0.10", "0.10", "X", "X", gene, count, blank_ws, num, removed, "M", "\n"])
238 else:
239 output.append([locus, "0.10", "0.10", "X", "X", gene, count, blank_ws, num, removed, "\n"])
240
241 #Otherwise calls average() or weighted_average() to find the aggregate w / count / standard deviation / standard error of the insertions within each gene; marks the gene if that's requested
242
243 else:
244 if not arguments.weighted:
245 (average, variance, stdev, stderr) = average(gene_summary[locus]["w"])
246 else:
247 (average, variance, stdev, stderr) = weighted_average(gene_summary[locus]["w"],gene_summary[locus]["s"])
248 if (arguments.marked and locus in marked_set):
249 output.append([locus, average, variance, stdev, stderr, gene, count, blank_ws, num, removed, "M", "\n"])
250 else:
251 output.append([locus, average, variance, stdev, stderr, gene, count, blank_ws, num, removed, "\n"])
252
253 #If a gene doesn't have any insertions, sets mean/var to 0.10 and Xs out sd/se, plus leaves count through removed blank because there were no reads.
254
255 else:
256 if (arguments.marked and locus in marked_set):
257 output.append([locus, "0.10", "0.10", "X", "X", gene, "", "", "", "", "M", "\n"])
258 else:
259 output.append([locus, "0.10", "0.10", "X", "X", gene, "", "", "", "", "\n"])
260
261 #Writes the aggregated fitness file
262
263 with open(arguments.summary, "wb") as csvfile:
264 writer = csv.writer(csvfile)
265 writer.writerows(output)
266
267 #If finding missing genes is not requested, just finds the aggregate w / count / standard deviation / standard error of the insertions within each gene, and writes them to a file, plus marks the genes requested
268 #This is never called through Galaxy since finding missing genes is just better than not finding them.
269
270 else:
271 output = [["Locus","W","Count","SD","SE","M\n"]]
272 for gene in gene_summary.keys():
273 sum = 0
274 num = 0
275 average = 0
276 if "w" not in gene_summary[gene]:
277 continue
278 for i in gene_summary[gene]["w"]:
279 sum += i
280 num += 1
281 average = sum/num
282 xminusxbars = 0
283 for i in w:
284 xminusxbars += (i-average)**2
285 if num > 1:
286 sd = math.sqrt(xminusxbars/(num-1))
287 se = sd / math.sqrt(num)
288 if (arguments.marked and locus in marked_set):
289 output.append([gene, average, num, sd, se, "M", "\n"])
290 else:
291 output.append([gene, average, num, sd, se, "\n"])
292 with open(arguments.summary, "wb") as csvfile:
293 writer = csv.writer(csvfile)
294 writer.writerows(output)
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390 #
391 # ~MMM=:DMMM?, +NMMO=,:~I8MMMMM8+, , ~I8MMMMMN87~?8NNMMN8: +NMND~ +MN= ,$MMMI ?M8, ,OM8, :MN+ =MM? ,MMDNMMD ,+DM8I, ,,:::~~~::::::::::
392 # IMMMNMM8I ,I8MM87~::+$8NNMMMMOI+=~~:, ,,:~=?$DNMMMMMMDOZI7ZDMMMD8I , , $M8+?8MM8I , 7MI +MN= ZMN, 8MD MMN8MMM, :$ONM8I+=:, ,,,::::~~~~~=====~:
393 # , ,DMNN7: , ,OMMN7==~::~=?8NNMMMMMMNNMMMMMMMMMMMN8OO8ODNMMMMMD~ , IMMNMN~ ,OM+ ,NM$ ,NMO, :MM$ , ,:::,,::::,, $MNMMNM, ,,, :?ONMMNN8?~,, , ,,,,,,,::~~=+++??=~
394 # ,,:=+????+, I$ :ZMMN8$~:,,, ,:=?7$O8DD8O$7+==+$O8DNMMMMMMMMM$ ?$, == ,~, ~NM= 8MD, ,OM8ZMMO , ,::::::~~~:,, ?MNMMZ ,,,,,, ,+7ONMNMD8O$+~, ,,,,,,::~====::
395 # ,:=IONMMMMMMMMMMM8: ZN$: ,~DMMMND7=, ,,:~====:=$DNMMMMMMMN88MMMZ +N$ , ,7DN8= =MN, IMM =DMN7 ,,,,,,,,,, ,~?, ,,,,, , ~?$8MMMMNN8Z?~:,, ,:::,,,
396 #+ONMMMMMMNO7=:,, ,,+MMO, 7D$: ~OMNMNNMNNNNNNNNNNNMMMMMMMMMNMMMM?,~MMM8 ND, 7MM=, ?NN:, +MO, ?MM, ,,,, , :,:=$DMMMMMMN87=~, ,,,,,
397 #MMND8$: , 7NM7 , =?~,,, :?88DDDNNMNNNDNDD88Z?:, ZMM$ ,MMMO ,MM+ZNMM? ::ZNZ, +M$ ,MM?, , ,, ,,:=?Z8NMMMMMN8Z+=,
398 #: ~ZMM8~ ,,,, 8MM, +MMM, 7ZZI~=$OOZ$: ,:+???+, +MZ =MN= ,,, , ,,:~=?IIII$ZO88DDNNNNNNMMMMMMMMMMN~,
399 # ,:OMMM? ,,:,, 8MM ~NNM7 :OMMMMMMMMO: =M8, :NM~ = ,~?I, ,,,,,,,,,,,,,, ,~$DNMMMMMMMMMND8O888Z$II7777I??+++===:,
400 # ?DMM8?, OMN??NMM$ ~8MMMO?===7MMM8: ~NM= =NN: ,OM~ ,, +NMMN~ ,,,,, ,,,,,,,, ,?$O8NNMDDZ7?+=~:, , , ,
401 # , ~$MMMD+ , , ~MMNMMN~ : +NMMZ, NMNM~ 7MI , ZNN,, IMN, :DMNM+ ~+NMMMD~, ,,,,,,,, ,, ,,,,,:, +OMNMMOI~,
402 # , $MMMM$, , ,=?ODNMNNMNMMMMNNND~ ,$D$, , ,8MM8 ,MMM7 ,ZMNNMM= DMMNMMMMMMMMMMMMNI: , ,,,,,,,,, ,,, ?NMO=, ,
403 # ,~ZNMND7, ,,:~=+$DNNMMMMNDDDD888OZZZZ8NMMN IMMN: ,MMN~ +Z$+, ?NNNDO+:?O888OI, ,,,,,,, ,,, +MN+
404 # =ONMMM8~ , ,:=IDMMMMMMMND8$+:, , ,INMNZ :MMM~, , +MMD , ,, ,,::,,,, ,,:::, ?M8: ,
405 #8MMMNZ~ , =I$ONMMNDZ7?+, ,,=I8NMD7: DMMN DMN= ,:::, ,:~~=~~:,, :ZMMZI+: ,, ,,,,,,,
406 #MN7:,:=7ONMMMD$?=, , ~7ODNMM$+: ~MMM++7ZOZOO8O8D8$~ ,MM8 ,,,,::~~==~~:,, :+7DMMMMNNDD88OOZZZO88DNNNN8=, ,,,,,,,
407 #I,~+DMMNND7: , ,$MMMMMN7, $MMN :??+=~::,,,, NMD, ,:,,:::~=~~,,,, ,,=I$8DNMMMMMMMMMNMMMNZ: ,,,,,,
408 #DNMNN7:, ,+ONMMMMNI: NMM$ DMN= ,,,,:::::~~::,, ?DMMMMDZ=, ,,,
409 #N8$: ,,, ,:=?ONMMMD8Z+, ,,,, MMM= ZMMI ,=?$8NMMMMMMMMMMMN87=~~,,, :=ZMMMMD$~
410 # , ,=ZNMMMMMNI:, ,~?Z88888$=, ,:~+??~, MMM, IMM$ ,=ZNMMMMMN8$+~=~=~~===7ODNMMMN8DNMMMN+, ,,
411 # , ~?$ODMMMMNZ?: :II+~, ,=7= :?77?=:====?O+ ,,:,,, MMM, ?MM$ ,,,, :?ONMM8II=, , =DMMMM87=, ,,,,
412 # , ,, ,~I8MMMMMMN87?~:=+?7$ZOO88DD888O$I+~:, ~ZZ: ,$7,~??, ,?+ ,+Z8$?==??= MMM =MM$ :?ODNNNNNNNMMO: ,:?NNMNO= ,,,IMMMNZ, ,,,:,,,,,,,,,,,,,
413 #, ,~7DNMMMMMMMMMMMNNNNMMMNND8Z7II7$$$$ZODNNNMND$, :O$: , ,IN$, I+ +ZZ=,, 7+ MMM =ODDDDNNNNNN8= :MM$ ?DDNN8?::,, ,,7NMM8, 7NMNZ~, :OMMM$, , ,,:::~~:,,,,,,,,,,,,,,,,,
414 #?8NMMMMMMMMMMMN8I:,,, ~$NMMM$ :87 +DM$ ID+~78I, O7 :=+~ MMM , , ?MM7 $NMN$, :I8MMMMMMNMDNNNNNNNNNDD88ZI=: ,ZMM7, +MMN~ ,,,:::,, ,,:,::::,,,,,,
415 #MMMD8DNMDZ7=: ,:=+7ZNNNDOZ~ =DI , :7MM7, IDDZI, =DN88ZI77$N? NMM: $MM= ~: =OMNZ+ ,=7DMMMMMMNDDOOOOZ$7IIIII77$ZOO8NNMMD$+~ :OND~, ,, MMN= ,,,,,,,,,,,,,
416 #: ,,, , ,:+ZNMNNMMNO?: +8? +NMN7 , , ON~ 8MM$ NMD, ,7MMMN, 7MMO, ,:ONMMMMN8I: ,~ZNMNN$, ~MM? , ZMNND?~: ,,, ,, ,,,,,,
417 # , , ,:~?7$ZZ8NNMMMNO7I=, ~D+ ZNO=, , :NM$: =MMM NMO ~NMNMMM :ZDN$, ,,=7DMD$?=, :?ZMD$: :DMNOZZZ$: ,,,,, ~IDMMMMMMMMMMMMMMMMMMMMM8~
418 # , =DMNNNNNNNN8$= : , ,,~?ODNZ: :DM? =: ,MMM7 +MN~ ,MM8:NMN INMZ, ,=ONOI , +NMZ ,,+ZDMMMMMMMN+, ,,,,,,, ,~?$ODNNNNNNNMMMMMMMMD= ,
419 # ,:::::~7$I?=: ,~78NMNMMMMM? :+Z+ M8 $MM, =, DMMD NMN DMO OMM77NMI, ?8$~ , ~ZDDDNNNNNMMMMMMMMNMNNNNNDD8Z+:, IMN: I8DNMMMMN7~: ,,,,,, +$O$, ~$DMMMMMMMD~ ,, ,
420 # :I+ :ID? ~ZDNNNNMMNO?~,, ,:::::=7ONMNNNDMMMN$ ,=IONNMMMMZ:, ~MO ,7MMMI $MN, , :MMN ?8NDDNND$~ +MM~ ,MM~=MMMNMD, =ONNDDNMMMMMMMMMMMMNNND88DNNNNNMMMMMMMNDO7+~::,:,7MM+ =DMMMNNO? ~ZMMMMM7::~INMMMMMMMMMMMMMN8:
421 #:MMM+,INMMM: ,:~+78NMMMM8?==++++++???++??I$Z77$$$$$$$7II??I$ZZO8MMMMM8Z7~ ,IZI ~77+ ?MMMMD88MN8+~, +8MO$OMMMMMNMMMZ, ~=: OMM? ,MM? ZMM~MMMM8~ ,:+7$$$$ZZ7?==: :8MDOZ$ZZZODMMMMMM8+, ,:=?$ZZOOOOOOZ$: , , ,=8MNMMMMMMMMMMNDZ$7$MMMMMMMMMMMMMMMMMMNI+?I7ZDNMMMMMMMMMM$,
422 #=MMMZ$MMMMMM~ ,::::~==~~+I$8NMMMMMN$::::::::,,, ,,=ONDDO$7II?+~, , ,,$DD87: =NND= , ,+$$=:~, ,:, ,MMD NMI ,~?Z8DND88$?: 8MM$MMMZ:=~:,~~:::,,,=$DNMND$MM8, ~DMNMMMN?, :7$7?+==~=:,,,,,,,, ,,,,,,, ,,,,,,::,,,,,:::::::,,,::::::,, ,OM$,7MMMMMMNZ= , ~8MMMMMMMNDO7I7MMMMMMMMMMMMN8Z7+?NMMMD,,
423 #NMMMMMM? ,++, ~=I??= :7$ 7MM+ 7M7 ,:?ZZ$MMM8NMZ~+, :?INMMM? +$NMMMNZ: :+?I7$$Z$O88D88DDDDNNNNNNNNNNNNNNNNNNDDNDDDNNNNNMMNMMMMMMMNNNN$:??~ ,+II?=, , ,, ,?I??+=~, :MMMMMNM
424 #MMMMMD~ ,:=++++++++++=~,,, +MMN: ,MMD, :M$ ,INMNMMMMMMMMMM~~~?D, :OMM8: ,+$8Z$+,,$MMMMMD, :IODDDD
425 #N$~,,, ,~I$8NMMMMMMMMMNMMMMMMMMMMMMMMMMNNNN7: ZMMMM? NMMMNZ~:, +$: ,NMNI:::~?8MMM7I? IO ~I$ODNNNDND8OO$I?DMMMD$I8NMMMMMMMNMNMMMMMMM8=, ,
426 # ,:~?ONMMMMNNNDDD8NMD+, ,~?Z8NMNM8=, , $MNNNMM? :DMMMNDD8DZ7$+, ,8NMMNMNMMMD$: =8, ,INMMMNZI?====+I$$8DDNMMMMMMNNNMND7, :~$DMMMNMO
427 # ,?DMMMMMNNNMMM+::~++ZMMMM8ZZZZZZ$II77II7???=~:, ,+DMN7 =NMM8, ,NMMNMNMN$?I7I77OZ~ ~8D$~, ,MMMMMMNM8: :DMMM, , DMO=ZMZ,
428 # ,?OMMN87=, IZNNNMMMMMMMMMMND7IIII??III$8DDNN8Z+, , ~MM ?OMMMM~ ,MMMMMZ+ ~I= IMMMO$$= ?NNM? MN~ +NM:
429 # IMM8~ =MD, ?N= :,, ,+77?=+, $8MM7::OMMMMMMZ+ I+, ?NI , :MMM8$ NNI, 7M$
430 # ,MMN $MD 7M+ ~ODNZ~, :7MMN? , $MMMN= 7MNMN: +8+ ,D8~ =MMDD8Z= =NMD OM7,
431 # OMMD~ IMN: =8O:,~+$OO? :IZ+: :ZMMNM8= =DMMI ~8MM8= , ,, :8M?,$MM, ::, DM, =Z~ ,I8DDDN8$DMN~ MN ,=Z8DNDZZ= MD: ,
432 # ,,,,,,,, ?8NNMM8$I????++=+8MMMD$77$ZDMMNMMMDNOZ~ :IZ8DOI~, =MMMNMNM8I:, ,7M8I +MND7 ~MNDDM8~ 7MI MM7 :8MDDM7 8N= ~ID$, ,:Z$?:,,,=ONNMNMD= ?M$ :: +MI ,,,,,,::~~:::,,,,,,, ,+OMO:, ,
433 # ,,,::~===~~:, ,~+I$88DNNNNNNNNNDNDD8O$?~:, ,7DNMNDMMMN~,ZMND$8NNDZ=, $M? ?NNN7 =MO OMD$MM= MMMINMO $M7 DN: 8MMD: ?D~ :O8ZDMMMMD=, ,ZN$ ,INNMD= :NO ,:+8MMMMMMMMDI:,::,,
434 #=~~~::~~::, ~?78MMMDNMM? :+I$DD87?=, OMNDO$7$OI: 7N+ ?MNMN~ MMMNM$ 7M$ 7M$ +NMMO, ?N~ ~8+ ~7NMMNNOI= ~?ONZ+ ~ZNND,$M8 ~MO $MMMMMMMMMM7:::~~~~~~=+++===~~~:::,,
435 # ,~ONMMNO~, :?8NNMN8?~ZNMMMMMMMMMNMMNDOI=~NM? =MMM+ NMMMO 8M$ ,MM, $MMMN =D, ,?N~ , ?NMMMNNNDDO8DDD887, ,$ND= :O$NMZ IMO ,IMMMMN$, 7NO, ,,,,,:,,,
436 # ,~IDMNN8OI, :~+$DMMMMMMMN87+=~~~~?ZDNNMM, ?NM? :NMN :MM7 ~MN ~DMMMN O~ :DD, ,MMMMNNOI:,, , ,=ZODD8D? :MMM: NMZ +8NM8, ,, :~ ,,~:,
437 # ,INNMMNNO+ :=78NNZIIONMNNDMMN ,7D~ :MN~ MNMM?=MM $? OD, ,IMD ,:8MNMNNNNNNNNMMNM7: :8~ ZND OMN7, :NNMMMMN :8MMMMMNZ=:
438 # :O88NMMN$=~:, ?MMN88NMMMD =MN? =, :NM +7$NO, =N8 , OMI, ,, 7M: ZDDND? MMO ,, +MM8?OMN: ,::
439 # :$NMMMNMM8I: ,8MD, +MMN= ,=?77=:ZMMM7 ?MN ~$+ 7M7 ,DZ :M~ IMM8: ,8MN, , ,,,, :MMD,=DMM+,?O8= , ,
440 # ,=I77$ONNNZ?+ONMZ =$D ,+=::+$8NNMNDNMD7?, ?MN :~~: ~D7 ,NI ,M7 ~?ZNZ?, 8MM~ =ZMMN~$MMMMMMMNMMD$ONMMMMD:
441 # ~DMM= ~I7=, =DMMMD7MMM, :+?=?O$: ~N: ~MN88D$: NMM=, ~MMMMMMMMMMMMOZMMMMMM7::8MMI
442 # , :DNNI :~IDMMND :::=?II?==~::ZN7=+I$ZZZ8DZ+~~: IMMM~ ~MMMNMMMMMI~:7NMMMMD7,: +NM8,
443 # :NMM7, ~MM+ ,,,:~==~~~: , OMMN: ?NNMMMMM8, ~NMNO, =MMMN?,,
444 # ,,,,,,,, ,$8MMO= ~M8 +MNO: ,MM~ , :: ,~, ,,:::,,,,
445 # ,::,,,, ~ONND+ OD+ ?NMD, ?? ,::::::,,
446 # :=+??=:,,,,, ~?$D87I: ~Z? =$DM$: ,::,,,,,,,,
447 # ,:~==~, :+=, $NNNNZ~ ,,:~~: , :DMMMI
448 # ,~~~~~:,,, ,,, ,~IMMMN8O+, ,:~?7$Z7~, :ZDMNNDNM8ZI
449 # ,,~~:,, , :$DNNMMN8?, , ,~7ZOO?: ,:$NMMMM? :7NMMD?,
450 # ,:~~:,,, $NMMMMMNMNO?~ ~?ODDD$=, :?8MMMMMD?~7NMMMD$~ :ONMMN?
451 # ,,,,,,,,, ?$DMMMMMMMMMMD$?=~, ,~7ZZODN87????I$ODNMDOZ$7I: ~$ZDMD7==~ =$ZDND$++~,
452 # ~?++=~~, ~+?II7ZNMMMMMM8$$$?~, ,~?II7Z8DDOZ$77II+: ~?IZDM8O$I~, :??$8MMNZZ7+,
453 # , , ,+D7 :=IZ8NMMMNNMNNO$= ,:?ZDNNMMMNMND8Z7=, =ZNMMMMMD?,, :ONMNMMMN?,
454 # ,MMMM7 ,,::~IONNMMNNDDD8OZI=, ,::::=+I$ONMNNNNDDDNNMMMMMMMMMD87: ,:~=ZNNNDOI, ~7$ZO8DDNNNNDD8O+:,
455 #~, +MMMMDI?~ ,~+Z8DNDNNMMMMDD$+:,,, , ,~?7O8DNNNNNNMMMMMNOOZI??++?IZ88$: ,,~ZDMMMMMMMMMMMMMMMMMMNNNNNMMMNND8$=,,
456 # ,~: NMMMMOZMM8: ,7DZ~ ,,~IONMMMMMMMMMNDZ+~: , ,=I8DNMMMMMNMNMMMMMDNMMMMNMMMNNNDDDDD8O8Z$7II+++IZDDMMNMN$,,
457 # :~: MMMMMNMMM+ :, +?DOI~ ,:~?7$$ZODDNMNN8Z7??+=~:, ,~=+?7I?=:,,,,:=?I7$$$$$$$ZZZOO8DDNNMMNNNNNMMMMNMZ+
458 # ~=, MMMMMMMM8 ,NNNO , ,~?ZDNMNNNNNNND8O7?:,,, ,~=7DMMMMMMMMMZ~
459 # ,:+~ ,MMMMMMMMO ~N8: ,,:~, ,:~:,,, ,:~, ,:~~=+++?7$O8DNNNNNMMN8$=, ~+$ZO8DNNMMNNNND8OOOZ$+:, :=+I8MMMMDOI
460 # ,=+ MMMMMMMMMDMZ, ~?: ,,,,, ,:~~~, ,NN?$NMMMMMMMMMMMN87~:,,,=+=:,,,,,,:?NMMNMMMMMMNNDNDI8MMM+ ,
461 # +=, $MMMN?$NMN, ,+?+:, ,,:~~:, :=~, 8M= , :7ONNNO?~, , :$NNMMMMMMMMMMMMMN,
462 # ,+? ,NNO,, , :ODNNNZ: :?777I= IMO ,,=$Z7+~ ,?NNMMNZ: :7NMMMMMNMMMM8 , ,IDND~
463 # ,=~, 7I :+I+~::,, ~?I~ , ,~=~==: ZMZ ?8I: :I$DND$?~ :?$8MMN$?: ?ZDMMMMMMMM7 +$NMMMMMI
464 # ~~ , ,=+=: ,== ::, , ZMM: ?NN8: ,7NMMNI, ,$NMMMO: =NMMMNMM+ I8NMMMM,
465 # ~= ,~:,,~~, ,:, ,,,, , ,, +MN8 ,~OMM8Z, :+ZMNDOI =IMMN8= ,=NNMO ?NMMMD
466 # ::, ,,,:: ,:, ,, =MMO~ , ?NMMMI, ,INMMMDI, ~DMMN+, NMO ?DNO~
467 # ,~, ,,,::, ,, , ,, ,INMND+: :MMM+ ~ZDDMMMD?~:$MMMMMMMMMMM?
468 # ,, :~~:, ,:, ,, :ZMMMMNNMMMN, ,=ONMMMMNM$,,,,,, ,,
469 #Z, :, ,, ,~=~, ,, ,=?7$I= , :~~~, ,,,,
470 #MD= :: ,,,, , ,, ,,,,
471 #MNMI :: ,,, ,,,,
472 #7MMM? , ,~: :~:, ,:,
473 # OMMMO: ~NMD, :=: :+=: ,,,
474 # ~MMMN8: NMMM~ +?: ,:=++~ ,:,,
475 # $MMMMMNI,?MMMMZ ,DM7 ,=I= ~+~~:, ,:,,,
476 # +MMO~OMMMMMMMMD MMM7 , , =$~ ?OZ+ ,:,
477 # ~NMN: :+DNN7MMMNMMMDODMMN+ :+?, +77+~: :::,
478 # IMM+ ,NMMMMMMMMN?NM7 ~7+, , :+$I, , +8? :+~
479 # =NMD, NMMMMMM8~ ?NN, =ND? ,=??: ,8NMMMM= :++
480 # +DO, ~ZZ$ODI :8M~ :=I8NMNMMD+, ,:~~=: , +8MO$DMD+ ~===~: :~~:
481 # :$~ 7NMD$, ZMM8I? ,~=: , ZNN7,:MM8~,OMNMD8DMM= ++:
482 # =ZNOI: ?DND= ,?I~ ,,,: ,$ND+ ?NMNNNNN7+, 7MN, ,=+~
483 # :ZI: :, ,=7: ::,, $NN= 7NMMMM7: :DMMMN8NMMDDMN7 ,::,
484 # ~?= ,,, ,ZM= DMMD8 ?MMMMNN7, ,I+ :~~,
485 # =+, ,,, ,, =Z8: +$~
486 # :~ ,,~~,
487 # :, ::,
488 # ::, ,:::,
489 # ,, ,~
490 # ,, ,,,
491 #
492 #