ARPA-SIMC / arkimaps

generazione mappe meteorologiche da modelli previsionali
GNU General Public License v2.0
0 stars 1 forks source link

Caso d'uso: report con mappa ritagliata #149

Closed edigiacomo closed 11 months ago

edigiacomo commented 1 year ago

In alcuni report è necessario includere una mappa ritagliata (vedi #74), comprensiva di titolo, legenda, eventuali linee di costa, confini amministrativi etc.

Qui un veloce esempio, prodotto con cartopy usando un PNG generato da arkimaps (la legenda è assolutamente casuale): tclim-report

Purtroppo, il ritaglio della mappa funziona solo usando un output "georeferenziabile", quindi ipotizzo che l'unica soluzione sia quella di postprocessare l'output di arkimaps, un po' come ho fatto nell'esempio qui sopra.

Che sia un postprocessatore integrato in arkimaps oppure a valle di questo, dovrebbe poter permettere di inserire:

  1. Titolo
  2. Legenda
  3. Linee di costa (opzionali)
  4. Shapefile (opzionali)

Nel caso in cui fosse esterno rispetto a arkimaps, come input servirebbero, oltre PNG "georeferenziabile" e ritagliato, la legenda, il bounding box (analogamente a #148) e la proiezione usata.

spanezz commented 1 year ago

ok, qui si parla di avere una catena di processazione cartografica a valle di Magics, e vorrei evitare di dover implementare un motore di layout da zero in un postprocessatore di arkimaps.

Nelle prove che hai fatto con Cartopy, ti sembra faccia al caso nostro?

edigiacomo commented 1 year ago

Sì, andrebbe benissimo farlo a valle con Cartopy, mi basterebbe avere modo, come in #148, di avere in output anche la legenda, il bounding box e il CRS dell'immagine.

spanezz commented 1 year ago

Considerazione tangenzialmente correlata: al momento gli script di rendering hanno la minor quantità di dipendenze possibili, per renderli facili da eseguire anche su nodi di cluster. Fino a #74 dipendeva da Python3, Pillow e Magics, da #74 anche da GDAL.

Qui si aggiungerebbero altre dipendenze, e a questo punto mi chiedo: sarebbe possibile pensare di avere le librerie python di arkimaps installate anche sui nodi dove si fa rendering? Cosí alcune delle funzioni di piú alto livello per le postprocessazioni si possono mettere in libreria invece di copiarne il codice negli script di render

edigiacomo commented 1 year ago

I report sono fatti ad-hoc su scenari particolari e quindi il rendering verrebbe fatto manualmente ogni tanto su qualche dato. Si potrebbe quindi pensare di non integrare la parte di processazione cartografica ma semplicemente rendere possibile effettuarla a valle, limitando quindi le dipendenze di arkimaps.

spanezz commented 1 year ago

Questo ha senso, e circoscriverebbe arkimaps evitando di farlo diventare un mostro tentacolare che fa tutto.

Può aver senso creare un progetto python per software che lavora sulla tarball in uscita da arkimaps, con codice tipo per iterare il contenuto e caricare i file .json che descrivono i prodotti e farci cose?

edigiacomo commented 1 year ago

Buona idea! Si potrebbe avere una libreria che permetta di lavorare con classi e funzioni che modellano i dati e metadati contenuti nei tarball di arkimaps, in modo da astrarre rispetto a file e al JSON al suo interno.

spanezz commented 1 year ago

La libreria la preferisci come un modulo dentro ad arkimaps, o come progetto a parte?

edigiacomo commented 1 year ago

Per me va benissimo anche dentro arkimaps, grazie!

spanezz commented 1 year ago

Inizio il lavoro nel branch issue149, nato da issue74.

Ho intenzione di cambiare da tar a zip il formato del bundle, in modo da rendere i bundle facilmente ispezionabili. Facendo due branch separati si può gestire il merge di issue74 senza impattare procedure operative col cambio di formato

spanezz commented 1 year ago

Alla fine ho implementato sia zip che tar, perché unzip al momento non supporta la lettura da standard input.

Ora se si usa -o ….zip allora crea uno zip, altrimenti crea un tar. Questo dovrebbe rendere piú sempice anche la messa in produzione, usando gli zip solo se/quando servono

spanezz commented 1 year ago

L'implementazione iniziale è in https://github.com/ARPA-SIMC/arkimaps/blob/issue149/arkimapslib/outputbundle.py

Ci sono dei Reader, dei Writer e delle strutture dati di supporto. I dati dei prodotti partono dalla classe Products.

Dovrebbe essere ora semplice prendere un output (tar o zip), passarlo al Reader appropriato e farsi istanziare l'oggetto Products già parsato.

È il momento buono per ragionare della struttura dei dati: mi sembra ancora tutto un po' improvvisato, anche se non mi vengono in mente al momento motivi ovvii per cambiare qualcosa

spanezz commented 1 year ago

Ho riallineato il branch su master. Cosa mancherebbe al fare merge di questo branch?

edigiacomo commented 1 year ago

Scusa @spanezz non ho ancora fatto una review adeguata.

edigiacomo commented 11 months ago

Ciao @spanezz ho iniziato a guardarci. Ho un dubbio: il campo legend_info mi risulta vuoto, forse viene attivato solo quando la legenda è attivata? Sarebbe utile averlo in ogni caso, in modo da poter generare una legenda standalone a partire dalle informazioni contenute in quel campo.

Inoltre, sarebbe utile avere la possibilità di leggere il PNG prodotto: in questo modo, potrei renderizzare la mappa finale (confezionata con titolo, legenda, vari confini, etc) a partire da PNG prodotto da arkimaps, informazioni geografiche e legenda.

spanezz commented 11 months ago

Chiarimenti dopo telefonata:

spanezz commented 11 months ago

Intanto i branch 'master' e 'issue149' hanno avuto modo di divergere significativamente e non sono piú facilmente mergiabili. Prima di implementare quanto detto mi servirà dedicare un po' di tempo a riallinearli

spanezz commented 11 months ago

Intanto i branch 'master' e 'issue149' hanno avuto modo di divergere significativamente e non sono piú facilmente mergiabili. Prima di implementare quanto detto mi servirà dedicare un po' di tempo a riallinearli

Ho rifatto il branch, ora è mergiabile

spanezz commented 11 months ago

In 232e85c0a7727e0461c4d8a1e420b1f1ad19d42b ho implementato la lettura di prodotti PNG: outputbundle.ZipReader.load_product(path) restituisce un oggetto bytes con il PNG dentro, che poi si può aprire direttamente da PIL come buffer di memoria o scrivere su disco

spanezz commented 11 months ago

E in 4f3517c1dd32d3c3d740fd1d9172f9c9cf695d8c ho implementato l'uso dei parametri di contouring per riempire legend_info. Puoi dare un'occhiata per vedere se va tutto?

edigiacomo commented 11 months ago

Grazie! Controllo!

edigiacomo commented 11 months ago

Ho provato con questo file erg5v2.grib.gz: adesso ottengo legend_info ma non ho più le informazioni geografiche.

In [4]: georefs = set()
   ...: with TarReader("out.tar") as reader:
   ...:     products = reader.products()
   ...:     for path, info in products.by_path.items():
   ...:         georefs.add(str(info.georef))
   ...: print(georefs)
{'{}'}

Ti chiedo anche se riesci a farmi uno script di esempio per iterare su tutte le terne (path, legend_info, georef), perché non ho capito benissimo qual è il modo migliore di farlo.

spanezz commented 11 months ago

Ho provato con questo file erg5v2.grib.gz: adesso ottengo legend_info ma non ho più le informazioni geografiche.

Ho provato a lanciare render con -v e mi dice:

2023-12-21 15:43:04,564 INFO orders tp6h+000: Order has still unsupported projection cylindrical

Vogliamo ragionare su come gestire questo tipo di proiezione?

Riferimenti:

spanezz commented 11 months ago

Ecco lo script di esempio, però ho barato: ho appena fatto push di una modifica che sposta le informazioni della legenda dal sommario di ogni reftime al sommario di ogni ricetta.

Visto che la legenda è definita nella ricetta, questo evita ripetizioni inutili e rende i dati piú facili da trovare nel risultato.

L'esempio:

#!/usr/bin/python3

import json
import sys

from arkimapslib.outputbundle import ZipReader

reader = ZipReader(sys.argv[1])
products = reader.products()
for path, info in products.by_path.items():
    georef = info.georef
    recipe_info = products.by_recipe[info.recipe]
    legend_info = recipe_info.legend_info
    print(json.dumps({"path": path, "georef": georef, "legend": legend_info}, indent=1))
edigiacomo commented 11 months ago

Ho provato a lanciare render con -v e mi dice:

2023-12-21 15:43:04,564 INFO orders tp6h+000: Order has still unsupported projection cylindrical

Vogliamo ragionare su come gestire questo tipo di proiezione?

Riferimenti:

Credo che cylindrical sia equivalente a EPSG:4326: https://github.com/ecmwf/magics/blob/4.11.0/src/decoders/TileDecoder.cc#L39-L46

Tuttavia, in prima battuta mi basta che funzioni con le proiezioni nella forma EPSG:...: pensavo di averlo testato con il flavour emro_web che usa EPSG:3857 ma probabilmente mi sono sbagliato io, scusami.

Ecco lo script di esempio

Grazie mille! E grazie anche per la modifica! Domani lo provo.

edigiacomo commented 11 months ago

Perfetto! Per me va benissimo, per la pagina di doc associata alle API preferisci che ti apra un'altra issue dedicata?

spanezz commented 11 months ago

Perfetto! Per me va benissimo, per la pagina di doc associata alle API preferisci che ti apra un'altra issue dedicata?

Sí grazie, cosí intanto facciamo merge di questo che ha parecchie modifiche rispetto a master

edigiacomo commented 11 months ago

Fatto! Per me puoi fare il merge.