blob: fbc3adb8be5242d2141984c64f30bc52f2e10d87 [file] [log] [blame]
avm9996300a40032020-05-07 21:02:32 +02001<?php
2if (php_sapi_name() != "cli")
3 exit();
4
5// Font dels nombres d'habitants: https://catsalut.gencat.cat/web/.content/minisite/catsalut/proveidors_professionals/registres_catalegs/documents/poblacio-referencia.pdf
6$HABITANTS = [
7 "Alt Pirineu i Aran" => 67277,
8 "Lleida" => 362850,
9 "Camp de Tarragona" => 607999,
10 "Terres de l'Ebre" => 176817,
11 "Girona" => 861753,
12 "Catalunya Central" => 526959,
avm999630b3b4072020-05-17 02:39:07 +020013 "Barcelona" => 5050190,
14 "Barcelona Ciutat" => 1693449,
15 "Metropolità Sud" => 1370709,
16 "Metropolità Nord" => 1986032,
avm9996300a40032020-05-07 21:02:32 +020017];
18
19$CODENAME = [
20 "Alt Pirineu i Aran" => "AltPirineuAran",
21 "Lleida" => "Lleida",
22 "Camp de Tarragona" => "CampDeTarragona",
23 "Terres de l'Ebre" => "TerresDeLEbre",
24 "Girona" => "Girona",
25 "Catalunya Central" => "CatalunyaCentral",
avm999630b3b4072020-05-17 02:39:07 +020026 "Barcelona" => "Barcelona",
27 "Barcelona Ciutat" => "BarcelonaCiutat",
28 "Metropolità Sud" => "MetropolitaSud",
29 "Metropolità Nord" => "MetropolitaNord",
avm9996300a40032020-05-07 21:02:32 +020030];
31
avm99963227cbb02020-06-09 13:51:25 +020032// Funció per obtenir el nombre de casos nous al dia originalDay+translation
33// a partir de les dades de la regió sanitaria (dataRegio).
avm9996300a40032020-05-07 21:02:32 +020034function getSumDay($originalDay, $translation, &$dataRegio) {
35 if ($translation >= 0)
36 $day = (clone $originalDay)->add(new DateInterval("P".abs($translation)."D"));
37 else
38 $day = (clone $originalDay)->sub(new DateInterval("P".abs($translation)."D"));
39
40 foreach ($dataRegio as $row) {
41 $rowDay = new DateTime($row["data"]);
42 if ($day == $rowDay) return $row["sum_numcasos"];
43 }
44
45 return 0;
46}
47
avm99963227cbb02020-06-09 13:51:25 +020048// Funció per fer una consulta a la taula de dades
avm9996300a40032020-05-07 21:02:32 +020049function query($soql) {
avm999634b07f162020-06-04 13:35:57 +020050 $url = "https://analisi.transparenciacatalunya.cat/resource/xuwf-dxjd.json?\$query=".urlencode($soql);
51 $raw = file_get_contents($url);
avm9996300a40032020-05-07 21:02:32 +020052 return json_decode($raw, true);
53}
54
avm99963227cbb02020-06-09 13:51:25 +020055// Demanem una llista del nombre de casos cada dia a cada regió sanitària
avm9996300a40032020-05-07 21:02:32 +020056$data = query("SELECT data, regiosanitariadescripcio AS regio, sum(numcasos) AS sum_numcasos
57WHERE
avm999634b07f162020-06-04 13:35:57 +020058 resultatcoviddescripcio = 'Positiu PCR' AND
avm9996300a40032020-05-07 21:02:32 +020059 regiosanitariadescripcio <> 'No classificat'
60GROUP BY regiosanitariadescripcio, data
61ORDER BY data ASC, regiosanitariadescripcio");
62
avm99963227cbb02020-06-09 13:51:25 +020063// Fem un array que tindrà com a elements un array per cada regió amb el
64// contingut de totes les files d'aquella regió
avm9996300a40032020-05-07 21:02:32 +020065$dataPerRegio = [];
66foreach ($data as $row) {
67 if (!isset($dataPerRegio[$row["regio"]])) $dataPerRegio[$row["regio"]] = [];
68 $dataPerRegio[$row["regio"]][] = $row;
69}
70
71$summary = [];
avm99963227cbb02020-06-09 13:51:25 +020072foreach ($dataPerRegio as $regio => $dataRegio) { // Per a cada regió
73 if (!in_array($regio, array_keys($CODENAME)))
74 die("[fatal error] No tenim contemplada la regió '".$regio."'.\n");
75
avm9996300a40032020-05-07 21:02:32 +020076 $summary[$regio] = [];
77
avm99963227cbb02020-06-09 13:51:25 +020078 // Veiem quin és el primer i l'últim dia de la sèrie
avm9996300a40032020-05-07 21:02:32 +020079 $oldestDay = new DateTime("today");
80 $newestDay = new DateTime();
81 $newestDay->setTimestamp(0);
82
83 foreach ($dataRegio as $row) {
84 $date = new DateTime($row["data"]);
85 if ($date < $oldestDay) $oldestDay = $date;
86 if ($date > $newestDay) $newestDay = $date;
87 }
88
avm99963227cbb02020-06-09 13:51:25 +020089 // Si l'últim dia és avui, posem que sigui ahir, perquè no volem informació
90 // incompleta sobre avui.
91 if ($oldestDay == (new DateTime("today")))
92 $oldestDay = new DateTime("yesterday");
93
94 // Ara calculem les rhos.
avm9996300a40032020-05-07 21:02:32 +020095 $rhos = [];
96
avm99963227cbb02020-06-09 13:51:25 +020097 // Considerem cada dia a partir de 6 dies després del primer dia, i fins al
98 // dia anterior a l'últim dia (extrems inclosos)
99 for ($currentDate = (clone $oldestDay)->add(new DateInterval("P6D"));
100 $currentDate < $newestDay;
101 $currentDate->add(new DateInterval("P1D"))) {
102 // Calculem la rho (velocitat reproductiva efectiva) per aquell dia.
103 // Fórmula: https://biocomsc.upc.edu/en/shared/avaluacio_risc.pdf
104 $num = getSumDay($currentDate, 1, $dataRegio) +
105 getSumDay($currentDate, 0, $dataRegio) +
106 getSumDay($currentDate, -1, $dataRegio);
avm9996300a40032020-05-07 21:02:32 +0200107
avm99963227cbb02020-06-09 13:51:25 +0200108 $den = getSumDay($currentDate, -4, $dataRegio) +
109 getSumDay($currentDate, -5, $dataRegio) +
110 getSumDay($currentDate, -6, $dataRegio);
111
112 if ($num != 0 && $den == 0) continue;
113
114 $rho = ($num == 0 ? 0 : $num/$den);
avm9996300a40032020-05-07 21:02:32 +0200115
116 $rhos[] = [
117 "data" => $currentDate->format("c"),
118 "rho" => $rho
119 ];
120 }
121
avm99963227cbb02020-06-09 13:51:25 +0200122 // Considerem cada dia a partir de 13 dies després del primer dia, i fins el
123 // dia anterior a l'últim dia (extrems inclosos)
124 for ($currentDate = (clone $oldestDay)->add(new DateInterval("P13D"));
125 $currentDate < $newestDay;
126 $currentDate->add(new DateInterval("P1D"))) {
127 // Calculem Rho_7 i IA_14
128 // Rho_7(t) := \sum_{i=0}^{7} Rho(t - i)
129 // IA_14(t) := \sum_{i=0}^{14} N(t - i),
130 // on N(j) és el nombre de casos nous confirmats per PCR el dia j.
avm9996300a40032020-05-07 21:02:32 +0200131 $sum = 0;
132
avm99963227cbb02020-06-09 13:51:25 +0200133 $p13Date = (clone $currentDate)->sub(new DateInterval("P13D"));
134 $p6Date = (clone $currentDate)->sub(new DateInterval("P6D"));
avm9996300a40032020-05-07 21:02:32 +0200135
136 foreach ($dataRegio as $row) {
137 $date = new DateTime($row["data"]);
avm99963227cbb02020-06-09 13:51:25 +0200138 if ($date >= $p13Date && $date <= $currentDate) {
avm9996300a40032020-05-07 21:02:32 +0200139 $sum += $row["sum_numcasos"];
140 }
141 }
142
143 $rhoAverage = 0;
144 $rhoCount = 0;
145
146 foreach ($rhos as $row) {
147 $date = new DateTime($row["data"]);
avm99963227cbb02020-06-09 13:51:25 +0200148 if ($date >= $p6Date && $date <= $currentDate) {
avm9996300a40032020-05-07 21:02:32 +0200149 ++$rhoCount;
150 $rhoAverage += $row["rho"];
151 }
152 }
153
avm99963227cbb02020-06-09 13:51:25 +0200154 // Si no hem trobat rhos (rhoCount == 0) és perquè el numerador no era 0
155 // però el denominador era sempre 0 al calcular les rhos. Aleshores, tot i
156 // que no poguem calcular la rho_7 a causa de no poder calcular les rho_t
157 // individuals, aquest fet ens indica que el creixement ha sigut altíssim,
158 // i per tant posem una rho_7 de 1000000000, que se surt de la gràfica.
159 $rhoAverage = ($rhoCount == 0 ? 1000000000 : $rhoAverage/$rhoCount);
avm9996300a40032020-05-07 21:02:32 +0200160
161 $summary[$regio][] = [
avm999630b3b4072020-05-17 02:39:07 +0200162 "data" => $currentDate->format("d/m/y"),
avm99963227cbb02020-06-09 13:51:25 +0200163 "ia14" => $sum*(1e5/$HABITANTS[$regio]),
avm9996300a40032020-05-07 21:02:32 +0200164 "rho7" => $rhoAverage
165 ];
166 }
167}
168
avm99963227cbb02020-06-09 13:51:25 +0200169// Posem les dades a diversos fitxers per tal que les pugui llegir el gnuplot
avm9996300a40032020-05-07 21:02:32 +0200170foreach ($summary as $regio => $summaryRegio) {
171 $file = fopen("/tmp/covid19graphgenerator-".$CODENAME[$regio].".dat", "w");
172
173 foreach ($summaryRegio as $row)
174 fwrite($file, $row["data"]." ".$row["ia14"]." ".$row["rho7"]."\n");
175
176 fclose($file);
177}