@@ -50,3 +50,61 @@ def make_ds(*, nx=10, ny=10):
5050
5151 assert np .all (ds1 .data == ds2 .data ), "original data should be same"
5252 assert not np .all (ds1 .data_y == ds2 .data_y ), "remapped data should be different"
53+
54+
55+ def test_combine_da_da ():
56+ # This is used in MM aircraft branch
57+
58+ from monet .util .combinetool import combine_da_to_da
59+
60+ # Make "model" data -- increasing up and south
61+ xv = yv = np .linspace (0 , 1 , 10 )
62+ zv = np .linspace (0 , 1 , 5 )
63+ x , y = np .meshgrid (xv , yv )
64+ data = np .empty ((zv .size , yv .size , xv .size ))
65+ for i in range (data .shape [0 ]):
66+ data [i ] = i + 0.2 * (1 - y )
67+ model = xr .Dataset (
68+ data_vars = {"data" : (("z" , "y" , "x" ), data )},
69+ coords = {
70+ "level" : ("z" , zv ),
71+ "latitude" : ("y" , yv ),
72+ "longitude" : ("x" , xv ),
73+ },
74+ )
75+
76+ # Make "aircraft" data -- tilted profile: ->U, NW->SE
77+ x0 , y0 = 0.1 , 0.9
78+ mx , my = 0.8 , - 0.8
79+ n = 30
80+ z = np .linspace (0 , 1 , n )
81+ x = x0 + mx * z
82+ y = y0 + my * z
83+ obs = xr .Dataset (
84+ data_vars = {"data_obs" : ("time" , np .ones (n ))}, # doesn't matter
85+ coords = {
86+ "time" : np .arange (n ),
87+ "level" : ("time" , z ),
88+ "latitude" : ("time" , y ),
89+ "longitude" : ("time" , x ),
90+ },
91+ )
92+
93+ # Combine (find closest model grid cell to each obs point)
94+ # NOTE: to use `merge`, must have matching `level` dims
95+ new = combine_da_to_da (model , obs , merge = False , interp_time = False )
96+
97+ # Check
98+ assert new .dims == {"z" : 5 , "y" : n , "x" : n }
99+ assert float (new .longitude .min ()) == pytest .approx (0.1 )
100+ assert float (new .longitude .max ()) == pytest .approx (0.9 )
101+ assert float (new .latitude .min ()) == pytest .approx (0.1 )
102+ assert float (new .latitude .max ()) == pytest .approx (0.9 )
103+ assert (new .latitude .isel (x = 0 ).values == obs .latitude .values ).all ()
104+ assert np .allclose (new .longitude .isel (y = 0 ).values , obs .longitude .values )
105+
106+ # Use orthogonal selection to get track
107+ a = new .data .values [:, new .y , new .x ]
108+ assert a .shape == (model .dims ["z" ], n ), "model levels but obs grid points"
109+ assert (np .diff (a .mean (axis = 0 )) >= 0 ).all (), "obs profile goes S"
110+ assert np .isclose (np .diff (a .mean (axis = 1 )), 1 , atol = 1e-15 , rtol = 0 ).all (), "obs profile goes U"
0 commit comments