@@ -424,6 +424,120 @@ def test_open_nexradlevel2_file(nexradlevel2_files):
424
424
assert len (head ) == msg_31_header_length [i ]
425
425
426
426
427
+ def test_open_nexradlevel2_msg1_file (nexradlevel2_msg1_file ):
428
+ with NEXRADLevel2File (nexradlevel2_msg1_file ) as fh :
429
+
430
+ # volume header
431
+ assert fh .volume_header ["tape" ] == b"AR2V0001."
432
+ assert fh .volume_header ["extension" ] == b"201"
433
+ assert fh .volume_header ["date" ] == 3761373184
434
+ assert fh .volume_header ["time" ] == 3362708995
435
+ assert fh .volume_header ["icao" ] == b"KLIX"
436
+
437
+ # meta_header 15
438
+ assert len (fh .meta_header ["msg_15" ]) == 62
439
+ assert fh .meta_header ["msg_15" ][0 ]["size" ] == 1208
440
+ assert fh .meta_header ["msg_15" ][0 ]["channels" ] == 0
441
+ assert fh .meta_header ["msg_15" ][0 ]["type" ] == 15
442
+ assert fh .meta_header ["msg_15" ][0 ]["seq_id" ] == 819
443
+ assert fh .meta_header ["msg_15" ][0 ]["date" ] == 13024
444
+ assert fh .meta_header ["msg_15" ][0 ]["ms" ] == 51522855
445
+ assert fh .meta_header ["msg_15" ][0 ]["segments" ] == 14
446
+ assert fh .meta_header ["msg_15" ][0 ]["seg_num" ] == 1
447
+ assert fh .meta_header ["msg_15" ][0 ]["record_number" ] == 0
448
+ # meta_header 13
449
+ assert len (fh .meta_header ["msg_13" ]) == 48
450
+ assert fh .meta_header ["msg_13" ][0 ]["size" ] == 1208
451
+ assert fh .meta_header ["msg_13" ][0 ]["channels" ] == 0
452
+ assert fh .meta_header ["msg_13" ][0 ]["type" ] == 13
453
+ assert fh .meta_header ["msg_13" ][0 ]["seq_id" ] == 0
454
+ assert fh .meta_header ["msg_13" ][0 ]["date" ] == 13023
455
+ assert fh .meta_header ["msg_13" ][0 ]["ms" ] == 43397314
456
+ assert fh .meta_header ["msg_13" ][0 ]["segments" ] == 14
457
+ assert fh .meta_header ["msg_13" ][0 ]["seg_num" ] == 1
458
+ assert fh .meta_header ["msg_13" ][0 ]["record_number" ] == 62
459
+ # meta header 18
460
+ assert len (fh .meta_header ["msg_18" ]) == 4
461
+ assert fh .meta_header ["msg_18" ][0 ]["size" ] == 1208
462
+ assert fh .meta_header ["msg_18" ][0 ]["channels" ] == 0
463
+ assert fh .meta_header ["msg_18" ][0 ]["type" ] == 18
464
+ assert fh .meta_header ["msg_18" ][0 ]["seq_id" ] == 0
465
+ assert fh .meta_header ["msg_18" ][0 ]["date" ] == 0
466
+ assert fh .meta_header ["msg_18" ][0 ]["ms" ] == 0
467
+ assert fh .meta_header ["msg_18" ][0 ]["segments" ] == 4
468
+ assert fh .meta_header ["msg_18" ][0 ]["seg_num" ] == 1
469
+ assert fh .meta_header ["msg_18" ][0 ]["record_number" ] == 110
470
+ # meta header 3
471
+ assert len (fh .meta_header ["msg_3" ]) == 1
472
+ assert fh .meta_header ["msg_3" ][0 ]["size" ] == 528
473
+ assert fh .meta_header ["msg_3" ][0 ]["channels" ] == 0
474
+ assert fh .meta_header ["msg_3" ][0 ]["type" ] == 3
475
+ assert fh .meta_header ["msg_3" ][0 ]["seq_id" ] == 5459
476
+ assert fh .meta_header ["msg_3" ][0 ]["date" ] == 13024
477
+ assert fh .meta_header ["msg_3" ][0 ]["ms" ] == 61897431
478
+ assert fh .meta_header ["msg_3" ][0 ]["segments" ] == 1
479
+ assert fh .meta_header ["msg_3" ][0 ]["seg_num" ] == 1
480
+ assert fh .meta_header ["msg_3" ][0 ]["record_number" ] == 114
481
+ # meta header 5
482
+ assert len (fh .meta_header ["msg_5" ]) == 1
483
+ assert fh .meta_header ["msg_5" ][0 ]["size" ] == 1208
484
+ assert fh .meta_header ["msg_5" ][0 ]["channels" ] == 0
485
+ assert fh .meta_header ["msg_5" ][0 ]["type" ] == 5
486
+ assert fh .meta_header ["msg_5" ][0 ]["seq_id" ] == 0
487
+ assert fh .meta_header ["msg_5" ][0 ]["date" ] == 0
488
+ assert fh .meta_header ["msg_5" ][0 ]["ms" ] == 0
489
+ assert fh .meta_header ["msg_5" ][0 ]["segments" ] == 1
490
+ assert fh .meta_header ["msg_5" ][0 ]["seg_num" ] == 1
491
+ assert fh .meta_header ["msg_5" ][0 ]["record_number" ] == 115
492
+ assert fh .msg_5 == OrderedDict (
493
+ [
494
+ ("message_size" , 0 ),
495
+ ("pattern_type" , 0 ),
496
+ ("pattern_number" , 0 ),
497
+ ("number_elevation_cuts" , 0 ),
498
+ ("clutter_map_group_number" , 0 ),
499
+ ("doppler_velocity_resolution" , 0 ),
500
+ ("pulse_width" , 0 ),
501
+ ("elevation_data" , []),
502
+ ]
503
+ )
504
+
505
+ # meta header 2
506
+ assert len (fh .meta_header ["msg_2" ]) == 1
507
+ assert fh .meta_header ["msg_2" ][0 ]["size" ] == 48
508
+ assert fh .meta_header ["msg_2" ][0 ]["channels" ] == 0
509
+ assert fh .meta_header ["msg_2" ][0 ]["type" ] == 2
510
+ assert fh .meta_header ["msg_2" ][0 ]["seq_id" ] == 29176
511
+ assert fh .meta_header ["msg_2" ][0 ]["date" ] == 13024
512
+ assert fh .meta_header ["msg_2" ][0 ]["ms" ] == 64889226
513
+ assert fh .meta_header ["msg_2" ][0 ]["segments" ] == 1
514
+ assert fh .meta_header ["msg_2" ][0 ]["seg_num" ] == 1
515
+ assert fh .meta_header ["msg_2" ][0 ]["record_number" ] == 116
516
+
517
+ # data header
518
+ assert len (fh .data_header ) == 5856
519
+ msg_31_header_length = [
520
+ 367 ,
521
+ 367 ,
522
+ 367 ,
523
+ 367 ,
524
+ 367 ,
525
+ 367 ,
526
+ 367 ,
527
+ 367 ,
528
+ 366 ,
529
+ 367 ,
530
+ 366 ,
531
+ 366 ,
532
+ 365 ,
533
+ 364 ,
534
+ 363 ,
535
+ 362 ,
536
+ ]
537
+ for i , head in enumerate (fh .msg_31_header ):
538
+ assert len (head ) == msg_31_header_length [i ]
539
+
540
+
427
541
def test_open_nexradlevel2_datatree (nexradlevel2_file ):
428
542
# Define kwargs to pass into the function
429
543
kwargs = {
@@ -485,6 +599,64 @@ def test_open_nexradlevel2_datatree(nexradlevel2_file):
485
599
assert dtree .attrs ["scan_name" ] == "VCP-11"
486
600
487
601
602
+ def test_open_nexradlevel2_msg1_datatree (nexradlevel2_msg1_file ):
603
+ # Define kwargs to pass into the function
604
+ kwargs = {
605
+ "sweep" : [0 , 1 , 2 , 5 , 7 ], # Test with specific sweeps
606
+ "first_dim" : "auto" ,
607
+ "reindex_angle" : {
608
+ "start_angle" : 0.0 ,
609
+ "stop_angle" : 360.0 ,
610
+ "angle_res" : 1.0 ,
611
+ "direction" : 1 , # Set a valid direction within reindex_angle
612
+ },
613
+ "fix_second_angle" : True ,
614
+ "site_coords" : True ,
615
+ }
616
+
617
+ # Call the function with an actual NEXRAD Level 2 file
618
+ dtree = open_nexradlevel2_datatree (nexradlevel2_msg1_file , ** kwargs )
619
+
620
+ # Assertions
621
+ assert isinstance (dtree , DataTree ), "Expected a DataTree instance"
622
+ assert "/" in dtree .subtree , "Root group should be present in the DataTree"
623
+ assert (
624
+ "/radar_parameters" in dtree .subtree
625
+ ), "Radar parameters group should be in the DataTree"
626
+ assert (
627
+ "/georeferencing_correction" in dtree .subtree
628
+ ), "Georeferencing correction group should be in the DataTree"
629
+ assert (
630
+ "/radar_calibration" in dtree .subtree
631
+ ), "Radar calibration group should be in the DataTree"
632
+
633
+ # Check if at least one sweep group is attached (e.g., "/sweep_0")
634
+ sweep_groups = [key for key in dtree .match ("sweep_*" )]
635
+ assert len (sweep_groups ) == 5 , "Expected at least one sweep group in the DataTree"
636
+
637
+ # Verify a sample variable in one of the sweep groups (adjust as needed based on expected variables)
638
+ sample_sweep = sweep_groups [0 ]
639
+ assert len (dtree [sample_sweep ].data_vars ) == 6
640
+ assert (
641
+ "DBZH" in dtree [sample_sweep ].data_vars
642
+ ), f"DBZH should be a data variable in { sample_sweep } "
643
+ assert dtree [sample_sweep ]["DBZH" ].shape == (360 , 460 )
644
+ # Validate coordinates are attached correctly
645
+ assert (
646
+ "latitude" in dtree [sample_sweep ]
647
+ ), "Latitude should be attached to the root dataset"
648
+ assert (
649
+ "longitude" in dtree [sample_sweep ]
650
+ ), "Longitude should be attached to the root dataset"
651
+ assert (
652
+ "altitude" in dtree [sample_sweep ]
653
+ ), "Altitude should be attached to the root dataset"
654
+
655
+ assert len (dtree .attrs ) == 10
656
+ assert dtree .attrs ["instrument_name" ] == "KLIX"
657
+ assert dtree .attrs ["scan_name" ] == "VCP-0"
658
+
659
+
488
660
@pytest .mark .parametrize (
489
661
"sweeps_input, expected_sweeps, should_raise" ,
490
662
[
0 commit comments