diff --git a/bin/xmet-spc-render b/bin/xmet-spc-render new file mode 100755 index 0000000..036f678 --- /dev/null +++ b/bin/xmet-spc-render @@ -0,0 +1,97 @@ +#! /usr/bin/env python3 + +import argparse +import cairo + +from xmet.config import Config +from xmet.db import Database, DatabaseOrder + +from xmet.spc import SPCOutlookParser, \ + SPCOutlook, \ + SPCOutlookMap, \ + SPCOutlookType + +def render_categorical(db: Database, + conus: SPCOutlookMap, + outlook: SPCOutlook, + args): + assets = { + 'conus': config['map']['conus_dark' if args.dark else 'conus'], + 'logo': config['map']['logo_dark' if args.dark else 'logo'] + } + + with cairo.SVGSurface(args.categorical, conus.width, conus.height) as surface: + cr = cairo.Context(surface) + + conus.draw_base_map_from_file(cr, assets['conus']) + conus.draw_categories(cr, outlook) + conus.draw_cities(cr, db) + conus.draw_logo(cr, assets['logo']) + conus.draw_legend(cr, SPCOutlookType.CATEGORICAL) + + if args.dark: + cr.set_source_rgb(1, 1, 1) + + conus.draw_annotation(cr, outlook, SPCOutlookType.CATEGORICAL) + +def render_probabilistic(db: Database, + conus: SPCOutlookMap, + outlook: SPCOutlook, + hazard: str, + path: str, + args): + assets = { + 'conus': config['map']['conus_dark' if args.dark else 'conus'], + 'logo': config['map']['logo_dark' if args.dark else 'logo'] + } + + with cairo.SVGSurface(path, conus.width, conus.height) as surface: + cr = cairo.Context(surface) + + conus.draw_base_map_from_file(cr, assets['conus']) + conus.draw_probabilities(cr, outlook, hazard.upper()) + conus.draw_cities(cr, db) + conus.draw_logo(cr, assets['logo']) + conus.draw_legend(cr, SPCOutlookType.PROBABILISTIC) + + if args.dark: + cr.set_source_rgb(1, 1, 1) + + hazard = ' '.join(map(lambda p: p.lower().capitalize(), hazard.split(' '))) + + conus.draw_annotation(cr, outlook, SPCOutlookType.PROBABILISTIC, hazard) + +argparser = argparse.ArgumentParser(description='Render graphical SPC outlooks from text file') +argparser.add_argument('--dark', action='store_true', help='Output dark mode graphics') +argparser.add_argument('--valid', type=str, help='Timestamp on or after most recent outlook') +argparser.add_argument('--day', type=int, help='Number of days from issuance outlook applies to') +argparser.add_argument('--categorical', type=str, help='Output categorical risk graphic file') +argparser.add_argument('--any-severe', type=str, help='Output probabilistic severe risk graphic file') +argparser.add_argument('--tornado', type=str, help='Output probabilistic hail risk graphic file') +argparser.add_argument('--hail', type=str, help='Output probabilistic hail risk graphic file') +argparser.add_argument('--wind', type=str, help='Output probabilistic wind risk graphic file') + +args = argparser.parse_args() + +config = Config.load() +db = Database.from_config(config) + +parser = SPCOutlookParser() +conus = SPCOutlookMap() + +outlook = SPCOutlook.for_timestamp(db, args.valid, args.day) + +if args.categorical is not None: + render_categorical(db, conus, outlook, args) + +if args.any_severe is not None: + render_probabilistic(db, conus, outlook, 'any severe', args.any_severe, args) + +if args.tornado is not None: + render_probabilistic(db, conus, outlook, 'tornado', args.tornado, args) + +if args.hail is not None: + render_probabilistic(db, conus, outlook, 'hail', args.hail, args) + +if args.wind is not None: + render_probabilistic(db, conus, outlook, 'wind', args.wind, args)