| 
									
										
										
										
											2025-02-11 21:42:22 -05:00
										 |  |  | #! /usr/bin/env python3 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import argparse | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-22 13:53:54 -05:00
										 |  |  | from xmet.db      import Database | 
					
						
							|  |  |  | from xmet.s3      import S3Bucket | 
					
						
							|  |  |  | from xmet.storm   import StormEvent | 
					
						
							|  |  |  | from xmet.archive import Archive | 
					
						
							| 
									
										
										
										
											2025-02-11 21:42:22 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | parser = argparse.ArgumentParser( | 
					
						
							|  |  |  |     description = 'Archive NEXRAD Level II data from Amazon S3' | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | parser.add_argument('--quiet',   action='store_true', help='Suppress output') | 
					
						
							|  |  |  | parser.add_argument('--dry-run', action='store_true', help='Do not actually archive data') | 
					
						
							| 
									
										
										
										
											2025-02-16 11:13:41 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | group = parser.add_mutually_exclusive_group() | 
					
						
							| 
									
										
										
										
											2025-02-17 11:05:21 -05:00
										 |  |  | group.add_argument('--exclude', action='append', type=str, help='Exclude types of events from ingest') | 
					
						
							|  |  |  | group.add_argument('--type',    action='append', type=str, help='Specify only given types of events to ingest') | 
					
						
							| 
									
										
										
										
											2025-02-16 11:13:41 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-22 13:53:54 -05:00
										 |  |  | parser.add_argument('db',                            help='XMET SQLite3 database') | 
					
						
							| 
									
										
										
										
											2025-02-17 11:05:21 -05:00
										 |  |  | parser.add_argument('csv-event-details',  nargs='+', help='Compressed storm event details CSV file') | 
					
						
							|  |  |  | parser.add_argument('archive-dir',                   help='Target archive directory') | 
					
						
							| 
									
										
										
										
											2025-02-11 21:42:22 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | args = parser.parse_args() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | db      = Database.connect(args.db) | 
					
						
							|  |  |  | bucket  = S3Bucket() | 
					
						
							|  |  |  | archive = Archive(getattr(args, 'archive-dir'), bucket) | 
					
						
							| 
									
										
										
										
											2025-02-16 11:13:41 -05:00
										 |  |  | exclude = None | 
					
						
							|  |  |  | types   = None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | if args.exclude is not None: | 
					
						
							|  |  |  |     exclude = {s: True for s in args.exclude} | 
					
						
							| 
									
										
										
										
											2025-02-15 21:51:22 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-16 11:13:41 -05:00
										 |  |  | if args.type is not None: | 
					
						
							|  |  |  |     types = {s: True for s in args.type} | 
					
						
							| 
									
										
										
										
											2025-02-11 21:42:22 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-17 11:05:21 -05:00
										 |  |  | for path in getattr(args, 'csv-event-details'): | 
					
						
							|  |  |  |     for event in StormEvent.each_from_csv_file(path): | 
					
						
							|  |  |  |         if args.exclude is not None and event.event_type in exclude: | 
					
						
							| 
									
										
										
										
											2025-02-16 11:13:41 -05:00
										 |  |  |             continue | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-17 11:05:21 -05:00
										 |  |  |         if args.type is not None and event.event_type not in types: | 
					
						
							| 
									
										
										
										
											2025-02-15 21:51:22 -05:00
										 |  |  |             continue | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-17 11:05:21 -05:00
										 |  |  |         if event.coord_start is None or event.coord_end is None: | 
					
						
							| 
									
										
										
										
											2025-02-13 19:19:27 -05:00
										 |  |  |             continue | 
					
						
							| 
									
										
										
										
											2025-02-11 22:31:26 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-17 11:05:21 -05:00
										 |  |  |         if not event.is_radar_significant(): | 
					
						
							| 
									
										
										
										
											2025-02-13 12:19:06 -05:00
										 |  |  |             continue | 
					
						
							| 
									
										
										
										
											2025-02-11 21:42:22 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-17 11:05:21 -05:00
										 |  |  |         radars = event.nearby_radars(db) | 
					
						
							| 
									
										
										
										
											2025-02-11 21:42:22 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-17 11:05:21 -05:00
										 |  |  |         for key in bucket.each_matching_key(radars, event.timestamp_start, event.timestamp_end): | 
					
						
							| 
									
										
										
										
											2025-02-13 12:19:06 -05:00
										 |  |  |             if archive.is_downloaded(key): | 
					
						
							|  |  |  |                 if not args.quiet: | 
					
						
							| 
									
										
										
										
											2025-02-17 11:05:21 -05:00
										 |  |  |                     print(f"event {event.id} key {key} type {event.event_type} already archived") | 
					
						
							| 
									
										
										
										
											2025-02-13 12:19:06 -05:00
										 |  |  |             else: | 
					
						
							|  |  |  |                 if not args.quiet: | 
					
						
							|  |  |  |                     if args.dry_run: | 
					
						
							| 
									
										
										
										
											2025-02-17 11:05:21 -05:00
										 |  |  |                         print(f"event {event.id} key {key} type {event.event_type} would archive") | 
					
						
							| 
									
										
										
										
											2025-02-13 12:19:06 -05:00
										 |  |  |                     else: | 
					
						
							| 
									
										
										
										
											2025-02-17 11:05:21 -05:00
										 |  |  |                         print(f"event {event.id} key {key} type {event.event_type} archiving") | 
					
						
							| 
									
										
										
										
											2025-02-11 21:42:22 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-13 12:19:06 -05:00
										 |  |  |                 if not args.dry_run: | 
					
						
							|  |  |  |                     archive.download(key) |