pandemaths.py 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-"
  3. """
  4. PandeMaths - 2020 - by psy (epsylon@riseup.net)
  5. You should have received a copy of the GNU General Public License along
  6. with PandeMaths; if not, write to the Free Software Foundation, Inc., 51
  7. Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  8. """
  9. VERSION = "v0.3_beta"
  10. RELEASE = "29032020"
  11. SOURCE1 = "https://code.03c8.net/epsylon/pandemaths"
  12. SOURCE2 = "https://github.com/epsylon/pandemaths"
  13. CONTACT = "epsylon@riseup.net - (https://03c8.net)"
  14. pandemic_model_variables_path = "model/pandemia.txt" # pandemia variables file
  15. extended_model_variables_path = "model/extended.txt" # extended model variables file
  16. simulation_templates_path = "templates/" # templates files
  17. reports_path = "reports/" # reports files
  18. import json, datetime, os, random, sys
  19. import matplotlib.pyplot as plt
  20. def model_maths():
  21. print("[Info] Reviewing Model ...\n")
  22. try:
  23. print(" "+"-"*5+"\n")
  24. f = open(pandemic_model_variables_path, "r")
  25. model_variables = f.readlines()
  26. f.close()
  27. for v in model_variables:
  28. print(" - "+str(v.replace("\n", "")))
  29. except:
  30. pass
  31. try:
  32. print("\n "+"-"*5+"\n")
  33. f = open(extended_model_variables_path, "r")
  34. extended_variables = f.readlines()
  35. f.close()
  36. for v in extended_variables:
  37. print(" - "+str(v.replace("\n", "")))
  38. except:
  39. pass
  40. print("\n "+"-"*5+"\n")
  41. def simulation():
  42. print("[Info] Defining ecosystem ...\n")
  43. total_population = input(" + Total population (default: 100000): ")
  44. try:
  45. total_population = int(total_population)
  46. except:
  47. total_population = 100000
  48. if not total_population:
  49. total_population = 100000
  50. starting_population = total_population
  51. infected_starting = input(" + Infected (at the beginning) population (default: 1): ")
  52. try:
  53. infected_starting = int(infected_starting)
  54. except:
  55. infected_starting = 1
  56. if not infected_starting or infected_starting < 1:
  57. infected_starting = 1
  58. infected = infected_starting
  59. print("\n "+"-"*5+"\n")
  60. print("[Info] Establishing time units ...\n")
  61. days = input(" + Number of days (default: 200): ")
  62. try:
  63. days = int(days)
  64. except:
  65. days = 200
  66. if not days:
  67. days = 200
  68. daily_rate_interaction = input(" + Daily rate of interaction between individuals (default: 2.50): ")
  69. try:
  70. daily_rate_interaction = int(daily_rate_interaction)
  71. except:
  72. daily_rate_interaction = 2.50
  73. if not daily_rate_interaction:
  74. daily_rate_interaction = 2.50
  75. print("\n "+"-"*5+"\n")
  76. template = input("+ CHOOSE: (O)pen Simulation or (L)oad template: ").upper()
  77. if template == "O": # New Simulation
  78. average_rate_duration = None
  79. probability_of_contagion = None
  80. recovery_rate = None
  81. simulation_name = "OPEN"
  82. new_simulation(total_population, infected_starting, days, daily_rate_interaction, average_rate_duration, probability_of_contagion, recovery_rate, simulation_name, starting_population)
  83. else: # Load template
  84. load_template(total_population, infected_starting, days, daily_rate_interaction, starting_population)
  85. def load_template(total_population, infected_starting, days, daily_rate_interaction, starting_population):
  86. print("\n "+"-"*5+"\n")
  87. print("[Info] Generating templates ...\n")
  88. import glob
  89. templates = {}
  90. i = 0
  91. for file in glob.iglob(simulation_templates_path + '*', recursive=False):
  92. if(file.endswith(".txt")):
  93. i = i +1
  94. f=open(file, 'r')
  95. template = f.read().replace('\n',' ')
  96. templates[i] = file.replace("templates/",""), template.upper() # add template to main dict
  97. f.close()
  98. for k,v in templates.items():
  99. print (" ["+str(k)+"] - "+str(v[0].replace(".txt","")))
  100. print("\n "+"-"*5+"\n")
  101. template_set = input("+ CHOOSE: Number of template (ex: 1): ").upper()
  102. try:
  103. template_set = int(template_set)
  104. except:
  105. template_set = 1
  106. if not template_set or template_set > len(templates) or template_set < 1:
  107. template_set = 1
  108. for k,v in templates.items():
  109. if template_set == k:
  110. simulation_name = v[0].replace(".txt","")
  111. average_rate_duration = int(v[1].split("DURATION:")[1].split(" ")[0])
  112. probability_of_contagion = int(v[1].split("CONTAGION:")[1].split(" ")[0])
  113. recovery_rate = int(v[1].split("RECOV:")[1].split(" ")[0])
  114. new_simulation(total_population, infected_starting, days, daily_rate_interaction, average_rate_duration, probability_of_contagion, recovery_rate, simulation_name, starting_population)
  115. def new_simulation(total_population, infected_starting, days, daily_rate_interaction, average_rate_duration, probability_of_contagion, recovery_rate, simulation_name, starting_population):
  116. print("\n "+"-"*5+"\n")
  117. print("[Info] Generating variables ...\n")
  118. if average_rate_duration == None:
  119. average_rate_duration = input(" + Average duration of illness (default: 12) (days): ")
  120. try:
  121. if average_rate_duration == 0:
  122. pass
  123. else:
  124. average_rate_duration = int(average_rate_duration)
  125. except:
  126. average_rate_duration = 12
  127. if average_rate_duration < 0 or average_rate_duration > 100:
  128. average_rate_duration = 12
  129. else:
  130. print(" + Average duration of illness: "+str(average_rate_duration)+" days")
  131. if probability_of_contagion == None:
  132. probability_of_contagion = input(" + Infection rate (default: 14%): ")
  133. try:
  134. if probability_of_contagion == 0:
  135. pass
  136. else:
  137. probability_of_contagion = int(probability_of_contagion)
  138. except:
  139. probability_of_contagion = 14
  140. if probability_of_contagion < 0 or probability_of_contagion > 100:
  141. probability_of_contagion = 14
  142. else:
  143. print(" + Infection rate: "+str(probability_of_contagion)+"%")
  144. if recovery_rate == None:
  145. recovery_rate = input(" + Recovery rate (default: 95%): ")
  146. try:
  147. if recovery_rate == 0:
  148. pass
  149. else:
  150. recovery_rate = int(recovery_rate)
  151. except:
  152. recovery_rate = 95
  153. if recovery_rate < 0 or recovery_rate > 100:
  154. recovery_rate = 95
  155. else:
  156. print(" + Recovery rate: "+str(recovery_rate)+"%")
  157. mortality = 100 - recovery_rate
  158. print("\n "+"-"*5+"\n")
  159. print("[Info] Building parameters ...\n")
  160. print(" + Mortality rate: "+str(mortality)+"%")
  161. mortality = mortality / 100
  162. recovery_rate = recovery_rate / 100
  163. probability_of_contagion = probability_of_contagion / 100
  164. infected = infected_starting
  165. susceptible_starting = int(total_population) - int(infected)
  166. susceptible = susceptible_starting # susceptitble at start
  167. recovered = 0 # recovered individuals at start
  168. deceased = 0 # deceases individuals at start
  169. print(" + Susceptible: "+str(susceptible))
  170. print(" + Recovered: "+str(recovered))
  171. print(" + Deceased: "+str(deceased))
  172. print("\n"+"-"*15+"\n")
  173. print("[Info] Launching Simulation: [ "+str(simulation_name)+" ] ...\n")
  174. total_contagion = 0
  175. recoveries = 0
  176. current_time = datetime.datetime.now() # current datetime
  177. if not os.path.exists(reports_path): # create folder for reports
  178. os.makedirs(reports_path)
  179. data = {
  180. 'METADATA': [
  181. {
  182. 'Simulation Name': str(simulation_name),
  183. 'Datetime': str(current_time)
  184. }
  185. ],
  186. 'ECOSYSTEM': [
  187. {
  188. 'Total Population': str(total_population),
  189. 'Infected (at the beginning)': str(infected_starting),
  190. 'Number of days': str(days),
  191. 'Daily rate of interaction between individuals': str(daily_rate_interaction),
  192. 'Average duration of illness': str(average_rate_duration),
  193. 'Infection rate': str(probability_of_contagion*100)+"%",
  194. 'Recovery rate': str(recovery_rate*100)+"%",
  195. 'Mortality': str(mortality*100)+"%",
  196. 'Susceptible': str(susceptible),
  197. 'Recovered': str(recovered),
  198. 'Deceased': str(deceased)
  199. }
  200. ],
  201. 'SIMULATION': [
  202. {}
  203. ]
  204. }
  205. if not os.path.exists(reports_path+"PandeMaths-report_"+str(current_time)): # create folder for reports
  206. os.makedirs(reports_path+"PandeMaths-report_"+str(current_time))
  207. with open(reports_path+"PandeMaths-report_"+str(current_time)+"/"+str("PandeMaths-report_"+str(current_time)+".txt"), 'a', encoding='utf-8') as f: # append into txt
  208. f.write("="*50+os.linesep)
  209. f.write("Simulation Name:"+str(simulation_name)+os.linesep)
  210. f.write("Infected (at the beginning):"+str(infected_starting)+os.linesep)
  211. f.write("Number of days:"+str(days)+os.linesep)
  212. f.write("Daily rate of interaction between individuals:"+str(daily_rate_interaction)+os.linesep)
  213. f.write("Average duration of illness:"+str(average_rate_duration)+os.linesep)
  214. f.write("Infection rate:"+str(probability_of_contagion*100)+"%"+os.linesep)
  215. f.write("Recovery rate:"+str(recovery_rate*100)+"%"+os.linesep)
  216. f.write("Mortality:"+str(mortality*100)+"%"+os.linesep)
  217. f.write("Susceptible:"+str(susceptible)+os.linesep)
  218. f.write("Recovered:"+str(recovered)+os.linesep)
  219. f.write("Deceased:"+str(deceased)+os.linesep)
  220. f.write("="*50+os.linesep)
  221. entire_population_infected = 0
  222. day_started = False
  223. plot_starting_population = []
  224. plot_days = []
  225. plot_contagion = []
  226. plot_recoveries = []
  227. plot_deaths = []
  228. plot_susceptible = []
  229. plot_infected = []
  230. plot_recovered = []
  231. plot_total_population = []
  232. plot_total_contagion = []
  233. plot_total_recovered = []
  234. plot_total_deceased = []
  235. plot_total_non_affected = []
  236. for i in range(0, days):
  237. if i > 0:
  238. try:
  239. status_rate = round(int(infected*100/total_population))
  240. except:
  241. status_rate = 100
  242. if status_rate < 11: # ENDEMIA (-11%)
  243. if susceptible > 0:
  244. status = "IMPACT LEVEL: ENDEMIC!"
  245. else:
  246. if int(total_population*100/starting_population) > 49:
  247. status = "PRACTICALLY ERRADICATED BUT AT LEAST HALF OF THE POPULATION HAS DIED!"
  248. else:
  249. status = "PRACTICALLY ERRADICATED!"
  250. elif status_rate > 10 and status_rate < 25: # EPIDEMIA (>10%<25%)
  251. if susceptible > 0:
  252. status = "IMPACT LEVEL: EPIDEMIC!"
  253. else:
  254. status = "IMPORTANT FOCUS OF INCUBATION!"
  255. else: # PANDEMIA (>25%)
  256. if susceptible > 0:
  257. status = "IMPACT LEVEL: PANDEMIC!"
  258. else:
  259. status = "MOSTLY OF THE POPULATION IS INCUBATING!"
  260. sir = susceptible+infected+recovered # S-I-R model
  261. try:
  262. contagion = round(infected*daily_rate_interaction*susceptible/sir*probability_of_contagion) # contagion rounded rate
  263. except:
  264. contagion = 100
  265. recoveries = round(infected*recovery_rate/average_rate_duration) # recoveries rounded rate
  266. deaths = round(infected*mortality/average_rate_duration) # deaths rounded rate
  267. susceptible = susceptible - contagion + recoveries - deaths
  268. infected = infected+contagion-recoveries-deaths
  269. recovered =recovered + recoveries
  270. deceased = deceased + deaths
  271. total_contagion = total_contagion + contagion
  272. total_recovered = recovered
  273. total_deceased = total_deceased + deaths
  274. total_population = starting_population - deceased
  275. total_non_affected = susceptible_starting+infected_starting+0+0-total_contagion
  276. day_started = True
  277. else: # related to the first day
  278. status = "STARTED!"
  279. contagion = 0
  280. recoveries = 0
  281. deaths = 0
  282. total_recovered = 0
  283. total_deceased = 0
  284. deceased = 0
  285. susceptible = total_population - infected
  286. recovered = 0
  287. total_contagion = infected_starting
  288. total_non_affected = susceptible
  289. if total_population < 0:
  290. total_population = 0
  291. if total_contagion < total_contagion < 0:
  292. total_contagion = 0
  293. if contagion > susceptible: # more individuals than susceptible cannot be infected
  294. contagion = susceptible
  295. if contagion < 1:
  296. contagion = 0
  297. if total_non_affected < 1: # cannot be negative non affected individuals
  298. total_non_affected = 0
  299. if recoveries < 1:
  300. recoveries = 0
  301. if susceptible + infected + recovered + deceased > starting_population:
  302. susceptible = int(starting_population - infected - recovered - deceased)
  303. deaths = int(recovered + deceased - starting_population)
  304. if deaths < 1:
  305. deaths = 0
  306. if deaths > total_population:
  307. deaths = total_population
  308. if deaths > infected:
  309. deaths = infected
  310. infected = 0
  311. if susceptible < 1: # cannot be negative susceptible individuals
  312. susceptible = 0
  313. if susceptible == 0:
  314. total_non_affected = 0
  315. if day_started == True:
  316. if int(contagion + recoveries + deaths) == 0: # infected final resolution phase solved by random results
  317. if infected > 0:
  318. deaths = random.randrange(infected)
  319. if deaths > infected:
  320. infected = deaths
  321. if infected == 1: # random final against Existentialism!
  322. res = random.randrange(2)
  323. if res == 1: # survive!
  324. recoveries = recoveries + 1
  325. else: # die!
  326. deaths = deaths + 1
  327. infected = infected+contagion-recoveries-deaths
  328. recovered = recovered + recoveries
  329. total_recovered = total_recovered + recoveries
  330. deceased = deceased+deaths
  331. if infected > starting_population:
  332. infected = starting_population
  333. if total_population > 0:
  334. if infected > 0:
  335. if total_non_affected > 0:
  336. print(" -> [DAY: "+str(i)+"]\n Status: "+str(status)+"\n Contagion: ("+str(int(contagion))+")["+str(round(contagion/total_population*100))+"%] - Recoveries: ("+str(int(recoveries))+")["+str(round(recoveries/total_population*100))+"%] - Deaths: ("+str(int(deaths))+")["+str(round(deaths/total_population*100))+"%] | Susceptible: ("+str(int(susceptible))+")["+str(round(susceptible/total_population*100))+"%] - Infected: ("+str(int(infected))+")["+str(round(infected/total_population*100))+"%] - Recovered: ("+str(int(recovered))+")["+str(round(recovered/total_population*100))+"%]")
  337. print(" Total Population: ("+str(int(total_population))+"/"+str(int(starting_population))+") - Total Contagion: ("+str(int(total_contagion))+")["+str(round(total_contagion/starting_population*100))+"%] - Total Recovered: (" +str(int(total_recovered))+")["+str(round(total_recovered/starting_population*100))+"%] - Total Deceased: ("+str(int(total_deceased))+")["+str(round(total_deceased/starting_population*100))+"%] - Total N/A: ("+str(int(total_non_affected))+")["+str(round(total_non_affected/starting_population*100))+"%]\n")
  338. else:
  339. if entire_population_infected == 0:
  340. total_contagion = starting_population
  341. susceptible = 0
  342. status = "ALL INFECTED !!!"
  343. print("-"*75+"\n")
  344. print(" -> [DAY: "+str(i)+"] -> [ THE ENTIRE POPULATION HAS BEEN INFECTED! ]\n Status: "+str(status)+"\n Contagion: ("+str(int(contagion))+")[100%] - Recoveries: ("+str(int(recoveries))+")["+str(round(recoveries/total_population*100))+"%] - Deaths: ("+str(int(deaths))+")["+str(round(deaths/total_population*100))+"%] | Susceptible: ("+str(int(susceptible))+")[0%] - Infected: ("+str(int(infected))+")[100%] - Recovered: ("+str(int(recovered))+")["+str(round(recovered/total_population*100))+"%]")
  345. entire_population_infected = entire_population_infected + 1
  346. print(" Total Population: ("+str(int(total_population))+"/"+str(int(starting_population))+") - Total Contagion: ("+str(int(total_contagion))+")["+str(round(total_contagion/starting_population*100))+"%] - Total Recovered: (" +str(int(total_recovered))+")["+str(round(total_recovered/starting_population*100))+"%] - Total Deceased: ("+str(int(total_deceased))+")["+str(round(total_deceased/starting_population*100))+"%] - Total N/A: ("+str(int(total_non_affected))+")["+str(round(total_non_affected/starting_population*100))+"%]\n")
  347. print("-"*75+"\n")
  348. else:
  349. print(" -> [DAY: "+str(i)+"]\n Status: "+str(status)+"\n Contagion: ("+str(int(contagion))+")[100%] - Recoveries: ("+str(int(recoveries))+")["+str(round(recoveries/total_population*100))+"%] - Deaths: ("+str(int(deaths))+")["+str(round(deaths/total_population*100))+"%] | Susceptible: ("+str(int(susceptible))+")[0%] - Infected: ("+str(int(infected))+")[100%] - Recovered: ("+str(int(recovered))+")["+str(round(recovered/total_population*100))+"%]")
  350. print(" Total Population: ("+str(int(total_population))+"/"+str(int(starting_population))+") - Total Contagion: ("+str(int(total_contagion))+")["+str(round(total_contagion/starting_population*100))+"%] - Total Recovered: (" +str(int(total_recovered))+")["+str(round(total_recovered/starting_population*100))+"%] - Total Deceased: ("+str(int(total_deceased))+")["+str(round(total_deceased/starting_population*100))+"%] - Total N/A: ("+str(int(total_non_affected))+")["+str(round(total_non_affected/starting_population*100))+"%]\n")
  351. export_to_txt(current_time, i, status, contagion, recoveries, deaths, susceptible, infected, recovered, deceased, total_population, total_contagion, total_recovered, total_deceased, total_non_affected) # generate txt
  352. export_to_json(data, current_time, i, status, contagion, recoveries, deaths, susceptible, infected, recovered, deceased, total_population, total_contagion, total_recovered, total_deceased, total_non_affected) # generate json
  353. export_to_graph(plot_starting_population, plot_days, plot_contagion, plot_recoveries, plot_deaths, plot_susceptible, plot_infected, plot_recovered, plot_total_population, plot_total_contagion, plot_total_recovered, plot_total_deceased, plot_total_non_affected, current_time, starting_population, i, contagion, recoveries, deaths, susceptible, infected, recovered, total_population, total_contagion, total_recovered, total_deceased, total_non_affected) # generate plotting graph
  354. else: # population has passed the pandemia
  355. status = "VACCINED! [ NO MORE INFECTED! ]"
  356. if entire_population_infected == 0:
  357. total_contagion = starting_population
  358. print("-"*75+"\n")
  359. print(" -> [DAY: "+str(i)+"] -> [ NO MORE INFECTED! ]\n Status: "+str(status)+"\n Contagion: ("+str(int(contagion))+")[0%] - Recoveries: ("+str(int(recoveries))+")["+str(round(recoveries/total_population*100))+"%] - Deaths: ("+str(int(deaths))+")["+str(round(deaths/total_population*100))+"%] | Susceptible: ("+str(int(susceptible))+")[0%] - Infected: ("+str(int(infected))+")[0%] - Recovered: ("+str(int(recovered))+")["+str(round(recovered/total_population*100))+"%]")
  360. print(" Total Population: ("+str(int(total_population))+"/"+str(int(starting_population))+") - Total Contagion: ("+str(int(total_contagion))+")["+str(round(total_contagion/starting_population*100))+"%] - Total Recovered: (" +str(int(total_recovered))+")["+str(round(total_recovered/starting_population*100))+"%] - Total Deceased: ("+str(int(total_deceased))+")["+str(round(total_deceased/starting_population*100))+"%] - Total N/A: ("+str(int(total_non_affected))+")["+str(round(total_non_affected/starting_population*100))+"%]\n")
  361. print("-"*75+"\n")
  362. export_to_txt(current_time, i, status, contagion, recoveries, deaths, susceptible, infected, recovered, deceased, total_population, total_contagion, total_recovered, total_deceased, total_non_affected) # generate txt
  363. export_to_json(data, current_time, i, status, contagion, recoveries, deaths, susceptible, infected, recovered, deceased, total_population, total_contagion, total_recovered, total_deceased, total_non_affected) # generate json
  364. export_to_graph(plot_starting_population, plot_days, plot_contagion, plot_recoveries, plot_deaths, plot_susceptible, plot_infected, plot_recovered, plot_total_population, plot_total_contagion, plot_total_recovered, plot_total_deceased, plot_total_non_affected, current_time, starting_population, i, contagion, recoveries, deaths, susceptible, infected, recovered, total_population, total_contagion, total_recovered, total_deceased, total_non_affected) # generate plotting graph
  365. break
  366. else:
  367. if total_deceased >= starting_population: # the entire population has died! [game over!]
  368. status = "FATAL! [ THE ENTIRE POPULATION HAS DIED! ]"
  369. contagion = 0
  370. recoveries = 0
  371. deaths = 0
  372. susceptible = 0
  373. total_population = 0
  374. total_non_affected = 0
  375. print(" -> [DAY: "+str(i)+"] -> FATAL! [ THE ENTIRE POPULATION HAS DIED! ]\n Status: "+str(status)+"\n Contagion: ("+str(int(contagion))+")[100%] - Recoveries: ("+str(int(recoveries))+")[0%] - Deaths: ("+str(int(deaths))+")[100%] - Susceptible: ("+str(int(susceptible))+")[0%] - Infected: ("+str(int(infected))+")[100%] - Recovered: ("+str(int(recovered))+")[0%]")
  376. print(" Total Population: ("+str(int(total_population))+"/"+str(int(starting_population))+") - Total Contagion: ("+str(int(total_contagion))+")["+str(round(total_contagion/starting_population*100))+"%] - Total Recovered: (" +str(int(total_recovered))+")["+str(round(total_recovered/starting_population*100))+"%] - Total Deceased: ("+str(int(total_deceased))+")["+str(round(total_deceased/starting_population*100))+"%] - Total N/A: ("+str(int(total_non_affected))+")["+str(round(total_non_affected/starting_population*100))+"%]\n")
  377. export_to_txt(current_time, i, status, contagion, recoveries, deaths, susceptible, infected, recovered, deceased, total_population, total_contagion, total_recovered, total_deceased, total_non_affected) # generate txt
  378. export_to_json(data, current_time, i, status, contagion, recoveries, deaths, susceptible, infected, recovered, deceased, total_population, total_contagion, total_recovered, total_deceased, total_non_affected) # generate json
  379. export_to_graph(plot_starting_population, plot_days, plot_contagion, plot_recoveries, plot_deaths, plot_susceptible, plot_infected, plot_recovered, plot_total_population, plot_total_contagion, plot_total_recovered, plot_total_deceased, plot_total_non_affected, current_time, starting_population, i, contagion, recoveries, deaths, susceptible, infected, recovered, total_population, total_contagion, total_recovered, total_deceased, total_non_affected) # generate plotting graph
  380. break
  381. status = "FINISHED!"
  382. if infected == 0:
  383. deaths = 0
  384. recoveries = 0
  385. contagion = 0
  386. print(" -> [DAY: "+str(i)+"] -> [ SIMULATION END! ]\n Status: "+str(status))
  387. print(" Total Population: ("+str(int(total_population))+"/"+str(int(starting_population))+") - Total Contagion: ("+str(int(total_contagion))+")["+str(round(total_contagion/starting_population*100))+"%] - Total Recovered: (" +str(int(total_recovered))+")["+str(round(total_recovered/starting_population*100))+"%] - Total Deceased: ("+str(int(total_deceased))+")["+str(round(total_deceased/starting_population*100))+"%] - Total N/A: ("+str(int(total_non_affected))+")["+str(round(total_non_affected/starting_population*100))+"%]\n")
  388. export_to_txt(current_time, i, status, contagion, recoveries, deaths, susceptible, infected, recovered, deceased, total_population, total_contagion, total_recovered, total_deceased, total_non_affected) # generate txt
  389. export_to_json(data, current_time, i, status, contagion, recoveries, deaths, susceptible, infected, recovered, deceased, total_population, total_contagion, total_recovered, total_deceased, total_non_affected) # generate json
  390. export_to_graph(plot_starting_population, plot_days, plot_contagion, plot_recoveries, plot_deaths, plot_susceptible, plot_infected, plot_recovered, plot_total_population, plot_total_contagion, plot_total_recovered, plot_total_deceased, plot_total_non_affected, current_time, starting_population, i, contagion, recoveries, deaths, susceptible, infected, recovered, total_population, total_contagion, total_recovered, total_deceased, total_non_affected) # generate plotting graph
  391. print("="*50 + "\n")
  392. generate_graph(starting_population, simulation_name, infected_starting, daily_rate_interaction, average_rate_duration, probability_of_contagion, recovery_rate, mortality, total_population, plot_starting_population, plot_days, plot_contagion, plot_recoveries, plot_deaths, plot_susceptible, plot_infected, plot_recovered, plot_total_population, plot_total_contagion, plot_total_recovered, plot_total_deceased, plot_total_non_affected, current_time) # generate final graph
  393. print ("[Info] [REPORTS] (txt|json|png) -> [SAVED!] at: '"+str(reports_path+"PandeMaths-report_"+str(current_time)+"/'")+"\n")
  394. def export_to_txt(current_time, i, status, contagion, recoveries, deaths, susceptible, infected, recovered, deceased, total_population, total_contagion, total_recovered, total_deceased, total_non_affected):
  395. if not os.path.exists(reports_path+"PandeMaths-report_"+str(current_time)): # create folder for reports
  396. os.makedirs(reports_path+"PandeMaths-report_"+str(current_time))
  397. with open(reports_path+"PandeMaths-report_"+str(current_time)+"/"+str("PandeMaths-report_"+str(current_time)+".txt"), 'a', encoding='utf-8') as f: # append into txt
  398. f.write(os.linesep)
  399. f.write("Day:"+str(i)+os.linesep)
  400. f.write("Status:"+str(status)+os.linesep)
  401. f.write("Contagion:"+str(contagion)+os.linesep)
  402. f.write("Recoveries:"+str(recoveries)+os.linesep)
  403. f.write("Deaths:"+str(deaths)+os.linesep)
  404. f.write("Susceptible:"+str(susceptible)+os.linesep)
  405. f.write("Infected:"+str(infected)+os.linesep)
  406. f.write("Recovered:"+str(recovered)+os.linesep)
  407. f.write("Deceased:"+str(deceased)+os.linesep)
  408. f.write("Total Population:"+str(total_population)+os.linesep)
  409. f.write("Total Contagion:"+str(total_contagion)+os.linesep)
  410. f.write("Total Deceased:"+str(total_deceased)+os.linesep)
  411. f.write("Total N/A:"+str(total_non_affected)+os.linesep)
  412. def export_to_json(data, current_time, i, status, contagion, recoveries, deaths, susceptible, infected, recovered, deceased, total_population, total_contagion, total_recovered, total_deceased, total_non_affected):
  413. data['SIMULATION'][0]['DAY'] = str(i)
  414. data['SIMULATION'][0]['Status'] = str(status)
  415. data['SIMULATION'][0]['Contagion'] = str(int(contagion))
  416. data['SIMULATION'][0]['Recoveries'] = str(int(recoveries))
  417. data['SIMULATION'][0]['Deaths'] = str(int(deaths))
  418. data['SIMULATION'][0]['Susceptible'] = str(int(susceptible))
  419. data['SIMULATION'][0]['Infected'] = str(int(infected))
  420. data['SIMULATION'][0]['Recovered'] = str(int(recovered))
  421. data['SIMULATION'][0]['Deceased'] = str(int(deceased))
  422. data['SIMULATION'][0]['Total Population'] = str(int(total_population))
  423. data['SIMULATION'][0]['Total Contagion'] = str(int(total_contagion))
  424. data['SIMULATION'][0]['Total Recovered'] = str(int(recovered))
  425. data['SIMULATION'][0]['Total Deceased'] = str(int(total_deceased))
  426. data['SIMULATION'][0]['Total N/A'] = str(int(total_non_affected))
  427. if not os.path.exists(reports_path+"PandeMaths-report_"+str(current_time)): # create folder for reports
  428. os.makedirs(reports_path+"PandeMaths-report_"+str(current_time))
  429. with open(reports_path+"PandeMaths-report_"+str(current_time)+"/"+str("PandeMaths-report_"+str(current_time)+".json"), 'a', encoding='utf-8') as f: # append into json
  430. json.dump(data, f, ensure_ascii=False, sort_keys=False, indent=4)
  431. def export_to_graph(plot_starting_population, plot_days, plot_contagion, plot_recoveries, plot_deaths, plot_susceptible, plot_infected, plot_recovered, plot_total_population, plot_total_contagion, plot_total_recovered, plot_total_deceased, plot_total_non_affected, current_time, starting_population, i, contagion, recoveries, deaths, susceptible, infected, recovered, total_population, total_contagion, total_recovered, total_deceased, total_non_affected):
  432. plot_starting_population = starting_population
  433. plot_days.append(i)
  434. plot_contagion.append(contagion)
  435. plot_recoveries.append(recoveries)
  436. plot_deaths.append(deaths)
  437. plot_susceptible.append(susceptible)
  438. plot_infected.append(infected)
  439. plot_recovered.append(recovered)
  440. plot_total_population.append(total_population)
  441. plot_total_contagion.append(total_contagion)
  442. plot_total_recovered.append(total_recovered)
  443. plot_total_deceased.append(total_deceased)
  444. plot_total_non_affected.append(total_non_affected)
  445. def generate_graph(starting_population, simulation_name, infected_starting, daily_rate_interaction, average_rate_duration, probability_of_contagion, recovery_rate, mortality, total_population, plot_starting_population, plot_days, plot_contagion, plot_recoveries, plot_deaths, plot_susceptible, plot_infected, plot_recovered, plot_total_population, plot_total_contagion, plot_total_recovered, plot_total_deceased, plot_total_non_affected, current_time):
  446. plt.plot(plot_days, plot_contagion, "blue", label="Contagion")
  447. plt.plot(plot_days, plot_recoveries, "grey", label="Recoveries")
  448. plt.plot(plot_days, plot_deaths, "orange", label="Deaths")
  449. plt.plot(plot_days, plot_susceptible, "cyan", label="Susceptible")
  450. plt.plot(plot_days, plot_infected, "purple", label="Infected")
  451. plt.plot(plot_days, plot_recovered, "brown", label="Recovered")
  452. plt.plot(plot_days, plot_total_population, "pink", label="Total Population")
  453. plt.plot(plot_days, plot_total_contagion, "red", label="Total Contagion")
  454. plt.plot(plot_days, plot_total_recovered, "yellow", label="Total Recovered")
  455. plt.plot(plot_days, plot_total_deceased, "black", label="Total Deceased")
  456. plt.plot(plot_days, plot_total_non_affected, "green", label="Total N/A")
  457. plt.plot(plot_starting_population)
  458. plt.title("SIMULATION: '"+str(simulation_name)+"' = Av_Ill: ["+str(average_rate_duration)+" days] - Inf_R: ["+str(probability_of_contagion*100)+"%] - Rec_R: ["+str(recovery_rate*100)+"%] - Mort: ["+str(mortality*100)+"%]\n\nTotal Population: ["+str(total_population)+"/"+str(starting_population)+"] - Infected (at the beginning): ["+str(infected_starting)+"] - Interaction (rate): ["+str(daily_rate_interaction)+"]\n")
  459. plt.xlabel('Day(s)')
  460. plt.ylabel('Individual(s)')
  461. plt.legend(loc='center left', fancybox=True, bbox_to_anchor=(1, 0.5))
  462. if not os.path.exists(reports_path+"PandeMaths-report_"+str(current_time)): # create folder for reports
  463. os.makedirs(reports_path+"PandeMaths-report_"+str(current_time))
  464. plt.savefig(reports_path+"PandeMaths-report_"+str(current_time)+"/"+str("PandeMaths-report_"+str(current_time)+".png"), bbox_inches='tight')
  465. def print_banner():
  466. print("\n"+"="*50)
  467. print(" ____ _ __ __ _ _ ")
  468. print("- _ \ __ _ _ __ __- - ___- \/ - __ _- -_- -__ ___ ")
  469. print("- -_) / _` - '_ \ / _` -/ _ \ -\/- -/ _` - __- '_ \/ __--2020")
  470. print("- __/ (_- - - - - (_- - __/ - - - (_- - -_- - - \__ /")
  471. print("-_- \__,_-_- -_-\__,_-\___-_- -_-\__,_-\__-_- -_-___/-by psy")
  472. print('\n"Pandemics Extensible Mathematical Model"')
  473. print("\n"+"-"*15+"\n")
  474. print(" * VERSION: ")
  475. print(" + "+VERSION+" - (rev:"+RELEASE+")")
  476. print("\n * SOURCES:")
  477. print(" + "+SOURCE1)
  478. print(" + "+SOURCE2)
  479. print("\n * CONTACT: ")
  480. print(" + "+CONTACT+"\n")
  481. print("-"*15+"\n")
  482. print("="*50)
  483. # sub_init #
  484. print_banner() # show banner
  485. try:
  486. option = input("\n+ CHOOSE: (M)odel or (S)imulation: ").upper()
  487. except:
  488. print("\n"+"="*50 + "\n")
  489. print ("[Info] Try to run the tool with Python3.x.y... (ex: python3 pandemaths) -> [EXITING!]\n")
  490. sys.exit()
  491. print("")
  492. print("="*50+"\n")
  493. if option == "S": # simulation
  494. simulation()
  495. else: # model
  496. model_maths()
  497. print ("="*50+"\n")