Home > Uncategorized > Open Pronto Soccorsi: come è fatto “dentro”

Open Pronto Soccorsi: come è fatto “dentro”


In questo post vedo di fornire qualche dettaglio su quelle che sono le caratteristiche e soluzioni tecniche che stanno alla base di Open Pronto Soccorsi.

ARCHITETTURA

Schematicamente l’architettura della soluzione è la seguente:

 

 

Nel diagramma sono citati i vari componenti del sistema che:

  • è ospitato su una macchina Ubuntu 14.0.4 LTS
  • utilizza come database SQLite3 + Spatialite 4.4.0
  • implementa la logica di business in PHP 5
  • si avvale di servizi di OpenStreetMap, OSM Buildings, Mapquest e Google ShortLink

Si tratta di una soluzione che utilizza tutti software open source e attinge da servizi disponibili in rete.

Per una soluzione più scalabile è possibile passare ad utilizzare POSTGRESQL con la sua estensione POSTGIS, non cambiando la logica di funzionamento.

Nel diagramma sono anche illustrati i passi delle diverse operazioni coinvolte e precisamente:

Se la consultazione avviene via web application da browser:

  • l’utente invia una richiesta dal proprio client (a)
  • il sistema interroga la propria base dato per recuperare il nome del comune indicato e le infomazioni di quali Pronto Soccorsi sono necessarie per la ricerca (b)
  • il sistema richiama le API di OpenProntoSoccorsi per ottenere le informazioni di dettaglio sui singoli Pronto soccorsi (c)
  • la parte di implementazione delle API recupera i dati di dettaglio per le interrogazioni di ogni singolo Pronto Soccorso (d)
  • la parte di implementazione delle API interroga le fonti dati (Servizi open data siti web via scraping) (e)

Se la consultazione avviene via bot Telegram:

  • l’utente invia una richiesta dal proprio client (1)
  • il sistema recupera le richieste con un’operazione di getUpdates (2)
  • effettua le ricerche su DB (3)
  • il sistema richiama le API di OpenProntoSoccorsi per ottenere le informazioni di dettaglio sui singolo Pronto soccorsi (4)
  • la parte di implementazione delle API interroga le fonti dati (Servizi open data siti web via scraping) (e)
  • nell’elaborazione della risposta invoca i servizi di Google Shortlink per abbreviare le url (5)
  • con un’operazione di sendMessage risponde (6)
  • Telegram inoltra la risposta al client (7)
  • l’utente può fruire dei diversi link contenuti nella risposta (8, 8a, 8b e 8c)

L’intero sistema, come indicato in figura può essere ospitato su un unico nodo Apache + PHP5.

Nella configurazione attuale del sistema questo è stato diviso su due nodi:

 

DATI
I dati principali utilizzati sono:

  • i dati geografici dei comuni italiani
  • i dati della localizzazione dei pronto soccorsi italiani (o meglio del loro ingresso ….)

COMUNI
Per i dati geografici dei comuni italiani la fonte dati è ISTAT:

https://www.istat.it/it/archivio/124086 (e precisamente lo scarico dei dati in WGS84 UTM32N quindi http://www.istat.it/storage/cartografia/confini_amministrativi/non_generalizzati/2016/Limiti_2016_WGS84.zip ).
tale dato lo si può scaricare con una wget e precisamente nel seguente modo

wget http://www.istat.it/storage/cartografia/confini_amministrativi/non_generalizzati/2016/Limiti_2016_WGS84.zip

Occorre ricordarsi che, se si è dietro ad un proxy occorre indicarlo, quindi l’istruzione diventa

wget -e use_proxy=yes -e http_proxy=<proxy>:<porta> http://www.istat.it/storage/cartografia/confini_amministrativi/non_generalizzati/2016/Limiti_2016_WGS84.zip

oppure con il comando curl nel seguente modo

curl -o Limiti_2016_WGS84.zip http://www.istat.it/storage/cartografia/confini_amministrativi/non_generalizzati/2016/Limiti_2016_WGS84.zip

Anche qui occorre ricordarsi che, se si è dietro ad un proxy occorre indicarlo, quindi l’istruzione diventa

curl --proxy <proxy>:<porta> -o Limiti_2016_WGS84.zip http://www.istat.it/storage/cartografia/confini_amministrativi/non_generalizzati/2016/Limiti_2016_WGS84.zip

A livello di struttura dati si mantiene quella standard dell’ISTAT: i campi che interessano principalmente sono:

  • COMUNE: toponimo del Comune
  • PRO_COM: codice ISTAT del Comune

Occorre trasformare i dati da EPSG4326 in EPSG32632 e quindi:

unzip Limiti_2016_WGS84.zip
ogr2ogr -t_srs EPSG:32632 comuni_From_ISTAT_32632.shp Limiti_2016_WGS84/Com2016_WGS84/Com2016_WGS84.shp

E’ quindi possibile eliminare files e directories temporanee:

rm Limiti_2016_WGS84.zip
rm -R Limiti_2016_WGS84

 

PRONTO SOCCORSI
Per i dati dei pronto soccorsi italiani questo dato non esiste in modalità “open”: alcuni dati sono su OSM ma non tutti quelli che servono.

Una fase preliminare delle attività è quindi stata quella di verificare, puntualmente, se sulla base dati OSM fosse presente il dato di interesse relativi ai singoli Pronto Soccorsi e, se non presente, provvedere ad inserire la localizzazione dell’ingresso dei pronto soccorsi.

Sul “come” mappare i Pronti Soccorsi non esiste una univocità di approccio (rif. https://lists.openstreetmap.org/pipermail/talk-it/2017-March/thread.html#57635 e, più recente, https://lists.openstreetmap.org/pipermail/talk-it/2018-July/thread.html#63667)
per cui se si ricontrassero errori o imprecisioni nei miei dati vi prego di segnalarmelo e sarà mia cura correggere eventuali errori.

Per recuperare i dati dei pronto soccorsi italiani è possibile utilizzare una query Overpass Turbo (rif. https://overpass-turbo.eu/), che è la seguente:

[out:json][timeout:250];
{{geocodeArea:Italia}}->.searchArea;
(
node["amenity"="hospital"]["emergency"="yes"](area.searchArea);
);
/out body;
>;
out skel qt;

Per eseguire la query da linea di comando è necessario, sempre da Overpass Turbo (rif. https://overpass-turbo.eu/), esportare la query come Overpass XML.

Si ottiene questo:

<osm-script output="json" output-config="" timeout="250">
<id-query into="searchArea" ref="3600365331" type="area"/>
<union into="_">
<query into="_" type="node">
<has-kv k="amenity" modv="" v="hospital"/>
<has-kv k="emergency" modv="" v="yes"/>
<area-query from="searchArea" into="_" ref=""/>
</query>
</union>
<print e="" from="_" geometry="skeleton" limit="" mode="body" n="" order="id" s="" w=""/>
<recurse from="_" into="_" type="down"/>
<print e="" from="_" geometry="skeleton" limit="" mode="skeleton" n="" order="quadtile" s="" w=""/>
</osm-script>

E’ necessario modificare il formato di output da `json` a `xml` in quanto risulterà più facile la successiva conversione automatica in ESRI shapefile e quindi il file è da trasformare in

<osm-script output="xml" output-config="" timeout="250">
<id-query into="searchArea" ref="3600365331" type="area"/>
<union into="_">
<query into="_" type="node">
<has-kv k="amenity" modv="" v="hospital"/>
<has-kv k="emergency" modv="" v="yes"/>
<area-query from="searchArea" into="_" ref=""/>
</query>
</union>
<print e="" from="_" geometry="skeleton" limit="" mode="body" n="" order="id" s="" w=""/>
<recurse from="_" into="_" type="down"/>
<print e="" from="_" geometry="skeleton" limit="" mode="skeleton" n="" order="quadtile" s="" w=""/>
</osm-script>

L’esecuzione della query da linea di comando è la seguente:

wget --post-file=ps_From_OSM.txt http://overpass-api.de/api/interpreter --output-document=ps_From_OSM.osm

Anche qui occorre ricordarsi che, se si è dietro ad un proxy occorre indicarlo e quindi l’istruzione diventa

wget -e use_proxy=yes -e http_proxy=<proxy>:porta> --post-file=ps_from_OSM.txt http://overpass-api.de/api/interpreter --output-document=ps_From_OSM.osm

A livello di struttura dati si mantiene quella di OSM.

Per convertire il file .osm in ESRI shapefile

ogr2ogr -nlt POINT -skipfailures TMP_DIR ps_From_OSM.osm

Occorre trasformare i dati da EPSG4326 in EPSG32632 e quindi:

ogr2ogr -t_srs EPSG:32632 ps_From_OSM_32632.shp TMP_DIR/points.shp

E’ quindi possibile eliminare files e directories temporanee:

rm ps_From_OSM.osm
rm -R TMP_DIR

A questo punto è possibile caricare i dati in Spatialite: il caricamento avviene manualmente usando Spatialite GUI

Una volta caricati i dati dei pronto soccorsi in Spatialite per calcolare le coordinate X e Y dei Pronto Soccorsi è possibile usare Spatialite nel seguente modo.

ALTER TABLE 'ps_From_OSM_32632' ADD COLUMN X REAL;
ALTER TABLE 'ps_From_OSM_32632' ADD COLUMN Y REAL;
UPDATE 'ps_From_OSM_32632' SET X=ST_X("Geometry") , Y=ST_Y("Geometry");

Per calcolare le coordinate Lat e Lon dei Pronto Soccorsi è possibile usare Spatialite nel seguente modo.

ALTER TABLE 'ps_From_OSM_32632' ADD COLUMN LON double;
ALTER TABLE 'ps_From_OSM_32632' ADD COLUMN LAT double;
UPDATE 'ps_From_OSM_32632' SET LON=ST_X(ST_Transform(geometry,4326));
UPDATE 'ps_From_OSM_32632' SET LAT=ST_Y(ST_Transform(geometry,4326));

 

QUALI PRONTO SOCCORSI PER COMUNE?
Poichè non tutti i comuni italiani hanno all’interno del loro territorio comunale un pronto soccorso è necessario capire come individuare i pronto soccorsi più vicini al comune in esame.

Considerando che:

  • calcolarlo dinamicamente ad ogni richiesta è onerso, anche in termini di tempi di risposta
  • le informazioni relative a comuni italiani e pronto soccorsi non sono informazioni che mutano così dinamicamente

si è deciso di preventivamente di ricavare queste informazioni di “vicinanza”.

Per “vicini” si intende i pronto soccorsi che ricadono “dentro” il comune e anche quelli più “vicini” all’area del comune.

La query spaziale da applicare in Spatialite è stata fornita da Alessandro Furieri sulla lista pubblica di Spatialite (rif. https://groups.google.com/forum/#!topic/spatialite-users/Hnpe_GdA6Pg ).

Ovviamente occorre prima di tutto caricare in Spatialite i layer dei comuni (comuni-From-ISTAT-32632) e dei pronto soccorso (ps-From-OSM-32632) creati in precedenza: questa operazione si può effettuare manualmente usando Spatialite GUI di dev fornita (quando si importano i dati dagli shapefiles ricordarsi di impostare esplicitamente il sistema di riferimento EPSG 32632, quindi indicare “32632” come numero)

Successivamente occorre dare i seguenti comandi:

#### Step 1 ####
CREATE TABLE dist_com_ps_1 AS
SELECT pg.ROWID AS pg_rowid,
pg.COMUNE AS pg_COMUNE,
pt.ROWID AS pt_rowid,
pt.OSM_ID as pt_osm_id,
pt.NAME AS pt_NAME,
pt.X AS pt_X,
pt.Y AS pt_Y,
pt.LON AS pt_LON,
pt.LAT AS pt_LAT,
ST_Distance(pg.geometry, pt.geometry) AS dist
FROM comuni_From_ISTAT_32632 AS pg, ps_From_OSM_32632 AS pt
ORDER BY pg_rowid, dist;

#### Step 2 ####
#### Creazione dell'indice per velocizzare la query ####
create index idx_dist_com_ps_1_pg_COMUNE_dist on dist_com_ps_1(pg_COMUNE, dist);

Esistono potenziali alternative che sono state suggerite per POSTGRESQL, in seguito ad una richiesta su
StackExchange (lista GIS – http://gis.stackexchange.com/questions/229505/the-first-n-points-near-a-polygon-spatialite-or-postgis-query), ma tali possibilità non sono state provate.

 

COME RECUPERARE LE INFO VIA SCRAPING
Per gestire i metadati necessari allo scraping delle pagine web da cui si traggono i dati di numeri e tempi di attesa la struttura della tabella di appoggio è la seguente:

osm_id: id del Pronto Soccorso come in OSM
ps_name: da mettere a mano (al più verificare corrispondenza con OSM ...)
city: da mettere a mano
address: da mettere a mano
tel: da mettere a mano
email: da mettere a mano
url_website: url del sito web dove sell'Ospedale ( Pronto Soccorso)
url_data: url del sito web dove ci sono i dati dei tempi e dei numeri dei pazienti in attesa
specific_function: da usare se serve una funzione specifica di parsing (altrimenti il valore è NO)
data_type: (HTML / JSON)
xpath_numeri_bianco: xpath dell'elemento della pagina HTML che contiene il numero di pazienti in attesa con codice bianco
xpath_tempi_bianco: xpath dell'elemento della pagina HTML che contiene il temp odi attesa per i pazienti in attesa con codice bianco
xpath_numeri_verde: xpath dell'elemento della pagina HTML che contiene il numero di pazienti in attesa con codice verde
xpath_tempi_verde: xpath dell'elemento della pagina HTML che contiene il temp odi attesa per i pazienti in attesa con codice verde
xpath_numeri_giallo: xpath dell'elemento della pagina HTML che contiene il numero di pazienti in attesa con codice giallo
xpath_tempi_giallo: xpath dell'elemento della pagina HTML che contiene il temp odi attesa per i pazienti in attesa con codice giallo
xpath_numeri_rosso: xpath dell'elemento della pagina HTML che contiene il numero di pazienti in attesa con codice rosso
xpath_tempi_rosso: xpath dell'elemento della pagina HTML che contiene il temp odi attesa per i pazienti in attesa con codice rosso

 

RIPORTARE SU MAPPA I PRONTO SOCCORSI
Per la parte di web mapping è necessario avere un layer dei pronto soccorsi da aggiungere sulla mappa.

Si può utilizzare un GeoJSON.

Da Spatialite è possibile creare una tabella che contiene le info che servono con questo comando:

CREATE TABLE ps_layer
AS SELECT
t2.osm_id as osm_id,
t2.ps_name as Nome,
t2.city as Citta,
t2.address as Indirizzo,
t2.url_website as Url,
t1.X as X,
t1.Y as Y,
t1.LON as LON,
t1.LAT as LAT
FROM ps_From_OSM_32632 AS t1, ps_details AS t2
WHERE t1.osm_id = t2.osm_id;

Questa tabella è poi caricabile come layer in QGIS, esportarla come file CSV e reimportarla come nuovo layer usando come coordinate i valori dei campi X e Y (attenzione che le coordinate sono espresse in EPSG:32632).

Infine è possibile salvare il tutto come GeoJSON avendo cura di indicare come sistema di riferimento EPSG:4326

Annunci
Categorie:Uncategorized
  1. Non c'è ancora nessun commento.
  1. No trackbacks yet.

Rispondi

Inserisci i tuoi dati qui sotto o clicca su un'icona per effettuare l'accesso:

Logo WordPress.com

Stai commentando usando il tuo account WordPress.com. Chiudi sessione /  Modifica )

Google+ photo

Stai commentando usando il tuo account Google+. Chiudi sessione /  Modifica )

Foto Twitter

Stai commentando usando il tuo account Twitter. Chiudi sessione /  Modifica )

Foto di Facebook

Stai commentando usando il tuo account Facebook. Chiudi sessione /  Modifica )

Connessione a %s...

%d blogger hanno fatto clic su Mi Piace per questo: