diff --git a/modules/aeolus/aeolus_amv.py b/modules/aeolus/aeolus_amv.py
index 1ac75ede36f614103eb8a047e5c3e59cb682387b..76f75cdc3e8f80cfb145719ae4cd16ecf899df5d 100644
--- a/modules/aeolus/aeolus_amv.py
+++ b/modules/aeolus/aeolus_amv.py
@@ -6,12 +6,13 @@ import xarray as xr
 from netCDF4 import Dataset, Dimension, Variable
 from aeolus.geos_nav import GEOSNavigation
 from util.util import haversine_np
-from amv.intercompare import best_fit
+from amv.intercompare import best_fit, bin_data_by, get_press_bin_ranges, spd_dir_from_uv, uv_from_spd_dir, direction_difference
 import math
+from metpy.units import units
 
 
 amv_file_duration = 60  # minutes
-half_width = 20  # search box centered on AEOLUS profile (FGF coordinates)
+half_width = 25  # search box centered on AEOLUS profile (FGF coordinates)
 num_elems = 5424
 num_lines = 5424
 
@@ -87,8 +88,8 @@ class OPS(AMVFiles):
         self.lon_name = 'lon'
         self.lat_name = 'lat'
 
-        self.out_params = {'Lon', 'Lat', 'Element', 'Line', 'pressure', 'wind_speed', 'wind_direction'}
-        self.params = {'pressure', 'wind_speed', 'wind_direction'}
+        self.out_params = ['Lon', 'Lat', 'Element', 'Line', 'pressure', 'wind_speed', 'wind_direction']
+        self.params = ['pressure', 'wind_speed', 'wind_direction']
         self.meta_dict = {'Lon': ('degrees east', 'f4'), 'Lat': ('degrees north', 'f4'), 'Element': (None, 'i4'), 'Line': (None, 'i4'),
                           'pressure': ('hPa', 'f4'), 'wind_speed': ('m s-1', 'f4'), 'wind_direction': ('degrees', 'f4')}
 
@@ -171,8 +172,8 @@ def match_amvs_to_raobs(raob_dict,  raob_time, amv_files):
 
     ds = Dataset(fname)
 
-    amv_lons = ds[amv_files.lon_name][:]
-    amv_lats = ds[amv_files.lat_name][:]
+    amv_lons = ds[amv_files.lon_name][:].data
+    amv_lats = ds[amv_files.lat_name][:].data
     if amv_files.elem_name is None or amv_files.line_name is None:
         cc, ll = nav.earth_to_lc_s(amv_lons, amv_lats)
     else:
@@ -184,12 +185,24 @@ def match_amvs_to_raobs(raob_dict,  raob_time, amv_files):
     param_s.append(amv_lats)
     param_s.append(cc)
     param_s.append(ll)
+
+    vld = None
     for param in amv_params:
+        data = ds[param][:]
+        if vld is None:
+            vld = np.invert(data.mask)
+        else:
+            vld = np.logical_and(vld, np.invert(data.mask))
         if param == 'V_3D':
-            param_s.append(ds[param][:, 0])
-            param_s.append(ds[param][:, 1])
+            param_s.append(data.data[0])
+            param_s.append(data.data[1])
         else:
-            param_s.append(ds[param][:])
+            param_s.append(data.data)
+
+    param_nd = np.vstack(param_s)
+    param_nd = param_nd[:, vld]
+    cc = param_nd[2, :]
+    ll = param_nd[3, :]
 
     ds.close()
 
@@ -215,10 +228,7 @@ def match_amvs_to_raobs(raob_dict,  raob_time, amv_files):
         num_amvs = np.sum(in_box)
         if num_amvs == 0:
             continue
-        # dist = haversine_np(lon, lat, amv_lons[in_box], amv_lats[in_box])
-        param_nd = np.vstack(param_s)
-        param_nd = param_nd[:, in_box]
-        match_dict[key] = param_nd
+        match_dict[key] = param_nd[:, in_box]
 
     return match_dict
 
@@ -317,9 +327,15 @@ def create_file2(filename, raob_to_amv_dct, raob_dct, amv_files):
     rootgrp.close()
 
 
+def bulk_stats(filename):
+    pass
+
+
 def analyze2(raob_to_amv_dct, raob_dct):
     keys = list(raob_to_amv_dct.keys())
 
+    amvs_list = []
+    bf_list = []
     for key in keys:
         rlat = key[0]
         rlon = key[1]
@@ -330,6 +346,7 @@ def analyze2(raob_to_amv_dct, raob_dct):
         raob_spd = raob[:, 2]
         raob_dir = raob[:, 3]
         amvs = raob_to_amv_dct.get(key)
+        amvs_list.append(amvs)
         num_amvs = amvs.shape[1]
         for i in range(num_amvs):
             amv_lon = amvs[0, i]
@@ -339,9 +356,118 @@ def analyze2(raob_to_amv_dct, raob_dct):
             amv_dir = amvs[6, i]
 
             bf = best_fit(amv_spd, amv_dir, amv_prs, amv_lat, amv_lon, raob_spd, raob_dir, raob_prs)
+            bf_list.append(bf)
             if bf[3] == 0:
-                print(nlevs, amv_prs, bf[2])
-
+                bspd, bdir = spd_dir_from_uv(bf[0], bf[1])
+                #print(amv_spd, bspd, amv_dir, bdir)
+
+    amvs = np.concatenate(amvs_list, axis=1)
+    amvs = np.transpose(amvs, axes=[1, 0])
+    bfs = np.stack(bf_list, axis=0)
+
+    good_amvs = amvs
+    num_good = good_amvs.shape[0]
+    didx = 6
+    sidx = 5
+    pidx = 4
+
+    spd_min = good_amvs[:, sidx].min()
+    spd_max = good_amvs[:, sidx].max()
+    print('spd min/max/mean: ', spd_min, spd_max, np.average(good_amvs[:, sidx]))
+
+    p_min = good_amvs[:, pidx].min()
+    p_max = good_amvs[:, pidx].max()
+    print('pres min/max/mean: ', p_min, p_max, np.average(good_amvs[:, pidx]))
+
+    low = good_amvs[:, pidx] >= 700
+    mid = np.logical_and(good_amvs[:, pidx] < 700, good_amvs[:, pidx] > 400)
+    hgh = good_amvs[:, pidx] <= 400
+
+    n_low = np.sum(low)
+    n_mid = np.sum(mid)
+    n_hgh = np.sum(hgh)
+
+    print('% low: ', 100.0*(n_low/num_good))
+    print('% mid: ', 100.0*(n_mid/num_good))
+    print('% hgh: ', 100.0*(n_hgh/num_good))
+    print('---------------------------')
+
+    print('Low Spd min/max/mean: ', good_amvs[low, sidx].min(), good_amvs[low, sidx].max(), good_amvs[low,sidx].mean())
+    print('Low Press min/max/mean: ', good_amvs[low, pidx].min(), good_amvs[low, pidx].max(), good_amvs[low, pidx].mean())
+    print('---------------------------')
+
+    print('Mid Spd min/max/mean: ', good_amvs[mid, sidx].min(), good_amvs[mid, sidx].max(), good_amvs[mid, sidx].mean())
+    print('Mid Press min/max/mean: ', good_amvs[mid, pidx].min(), good_amvs[mid, pidx].max(), good_amvs[mid, pidx].mean())
+    print('---------------------------')
+
+    print('Hgh Spd min/max/mean: ', good_amvs[hgh, sidx].min(), good_amvs[hgh, sidx].max(), good_amvs[hgh, sidx].mean())
+    print('Hgh Press min/max/mean: ', good_amvs[hgh, pidx].min(), good_amvs[hgh, pidx].max(), good_amvs[hgh, pidx].mean())
+
+    bin_size = 200.0
+    vld_bf = bfs[:, 3] == 0
+    keep_idxs = vld_bf
+
+    amv_p = good_amvs[keep_idxs, pidx]
+    bf_p = bfs[keep_idxs, 2]
+    diff = amv_p - bf_p
+    mad = np.average(np.abs(diff))
+    bias = np.average(diff)
+    print('********************************************************')
+    print('num of best fits: ', bf_p.shape[0])
+    print('press, MAD: ', mad)
+    print('press, bias: ', bias)
+    pd_std = np.std(diff)
+    pd_mean = np.mean(diff)
+    print('press bias/rms ', pd_mean, np.sqrt(pd_mean**2 + pd_std**2))
+    print('------------------------------------------')
+
+    bin_ranges = get_press_bin_ranges(50, 1050, bin_size=bin_size)
+    bin_pres = bin_data_by(diff, amv_p, bin_ranges)
+
+    amv_spd = good_amvs[keep_idxs, sidx]
+    amv_dir = good_amvs[keep_idxs, didx]
+    bf_spd, bf_dir = spd_dir_from_uv(bfs[keep_idxs, 0], bfs[keep_idxs, 1])
+
+    diff = amv_spd * units('m/s') - bf_spd
+    spd_mad = np.average(np.abs(diff))
+    spd_bias = np.average(diff)
+    print('spd, MAD: ', spd_mad)
+    print('spd, bias: ', spd_bias)
+    spd_mean = np.mean(diff)
+    spd_std = np.std(diff)
+    print('spd MAD/bias/rms: ', np.average(np.abs(diff)), spd_mean, np.sqrt(spd_mean**2 + spd_std**2))
+    print('-----------------')
+    bin_spd = bin_data_by(diff, amv_p, bin_ranges)
+
+    dir_diff = direction_difference(amv_dir, bf_dir.magnitude)
+    print('dir, MAD: ', np.average(np.abs(dir_diff)))
+    print('dir bias: ', np.average(dir_diff))
+    print('-------------------------------------')
+    bin_dir = bin_data_by(dir_diff, amv_p, bin_ranges)
+
+    amv_u, amv_v = uv_from_spd_dir(good_amvs[keep_idxs, sidx], good_amvs[keep_idxs, didx])
+    u_diffs = amv_u - (bfs[keep_idxs, 0] * units('m/s'))
+    v_diffs = amv_v - (bfs[keep_idxs, 1] * units('m/s'))
+
+    vd = np.sqrt(u_diffs**2 + v_diffs**2)
+    vd_mean = np.mean(vd)
+    vd_std = np.std(vd)
+    print('VD bias/rms: ', vd_mean, np.sqrt(vd_mean**2 + vd_std**2))
+    print('------------------------------------------')
+
+    x_values = []
+    num_pres = []
+    num_spd = []
+    num_dir = []
+    for i in range(len(bin_ranges)):
+        x_values.append(np.average(bin_ranges[i]))
+        num_pres.append(bin_pres[i].shape[0])
+        num_spd.append(bin_spd[i].shape[0])
+        num_dir.append(bin_dir[i].shape[0])
+
+    #return x_values, bin_pres, num_pres, bin_spd, num_spd, bin_dir, num_dir
+
+    return amvs, bfs
 
 
 # imports the S4 NOAA output