def zsample(d, zres=None, zlim=None): b = d['backscatter'] if 'backscatter_mol' in d: bmol = d['backscatter_mol'] if len(b.shape) == 3: n, m, l = b.shape dims = (n, m, l) else: n, m = b.shape l = 0 dims = (n, m) dims_mol = (n, m) b_sd = d['backscatter_sd'] if 'backscatter_sd' in d \ else np.zeros(dims, dtype=np.float64) zfull = d['zfull'] zhalf = np.zeros((n, m + 1), dtype=np.float64) for i in range(n): zhalf[i,:] = misc.half(zfull[i,:]) \ if zfull.ndim == 2 \ else misc.half(zfull) r = d['range'] if 'range' in d \ else np.zeros(m, dtype=np.float64) if m == 0: return zhalf2 = np.arange(zlim[0], zlim[-1] + zres, zres) zfull2 = (zhalf2[1:] + zhalf2[:-1]) * 0.5 m2 = len(zfull2) dims2 = (n, m2, l) if len(b.shape) == 3 else (n, m2) dims_mol2 = (n, m2) b2 = np.zeros(dims2, dtype=np.float64) b_sd2 = np.zeros(dims2, dtype=np.float64) bmol2 = np.zeros(dims_mol2, dtype=np.float64) # r2 = np.zeros(m2, dtype=np.float64) if l == 0: for i in range(n): b2[i, :] = interp(zhalf[i, :], b[i, :], zhalf2) b_sd2[i, :] = interp(zhalf[i, :], b_sd[i, :], zhalf2) else: for i in range(n): for j in range(l): b2[i, :, j] = interp(zhalf[i, :], b[i, :, j], zhalf2) b_sd2[i, :, j] = interp(zhalf[i, :], b_sd[i, :, j], zhalf2) if 'backscatter_mol' in d: for i in range(n): bmol2[i, :] = interp(zhalf[i, :], bmol[i, :], zhalf2) # d['range'] = r2 d['zfull'] = zfull2 d['backscatter'] = b2 if 'backscatter_mol' in d: d['backscatter_mol'] = bmol2 if 'backscatter_sd' in d: d['backscatter_sd'] = b_sd2 d['.']['zfull']['.dims'] = ['level']
def couple(d, d_idx): dims = d['backscatter'].shape n = dims[0] l = dims[2] if len(dims) == 3 else 0 couple_bsd = False couple_bmol = False if 'backscatter_sd' not in d: couple_bsd = True d['backscatter_sd'] = np.full(dims, np.nan, np.float64) d['.']['backscatter_sd'] = { '.dims': ['time', 'range', 'column'] \ if len(dims) == 3 \ else ['time', 'range'], 'long_name': 'total_attenuated_backscatter_coefficient_standard_deviation', 'units': 'm-1 sr-1', } if 'backsatter_mol' not in d: couple_bmol = True d['backscatter_mol'] = np.full(dims, np.nan, np.float64) d['.']['backscatter_mol'] = { '.dims': ['time', 'range', 'column'] \ if len(dims) == 3 \ else ['time', 'range'], 'long_name': 'total_attenuated_molecular_backscatter_coefficient', 'units': 'm-1 sr-1', } for i in range(n): t = d['time'][i] j = np.argmin(np.abs(d_idx['time'] - t)) n1 = d_idx['n'][j] filename = d_idx['filename'][n1] i1 = d_idx['i'][j] d1 = ds.read(filename, VARIABLES, {'time': i1}) zhalf1 = misc.half(d1['zfull']) zhalf = misc.half(d['zfull'][i,:]) \ if d['zfull'].ndim == 2 \ else misc.half(d['zfull']) if couple_bsd and 'backscatter_sd' in d1: b_sd = interp(zhalf1, d1['backscatter_sd'], zhalf) if len(dims) == 3: for k in range(l): d['backscatter_sd'][i, :, k] = b_sd else: d['backscatter_sd'][i, :] = b_sd if couple_bmol and 'backscatter_mol' in d1: b_mol = interp(zhalf1, d1['backscatter_mol'], zhalf) if len(dims) == 3: for k in range(l): d['backscatter_mol'][i, :, k] = b_mol else: d['backscatter_mol'][i, :] = b_mol
def couple(d, d_idx): n, m, l = d['backscatter'].shape d['backscatter_sd'] = np.full((n, m, l), np.nan, np.float64) d['.']['backscatter_sd'] = { '.dims': ['time', 'range', 'column'], 'long_name': 'total_attenuated_backscatter_coefficient_standard_deviation', 'units': 'm-1 sr-1', } for i in range(n): t = d['time'][i] j = np.argmin(np.abs(d_idx['time'] - t)) n1 = d_idx['n'][j] filename = d_idx['filename'][n1] i1 = d_idx['i'][j] d1 = ds.read(filename, ['zfull', 'backscatter_sd'], {'time': i1}) zhalf1 = misc.half(d1['zfull']) zhalf = misc.half(d['zfull'][i, :]) b_sd = interp(zhalf1, d1['backscatter_sd'], zhalf) for k in range(l): d['backscatter_sd'][i, :, k] = b_sd
def plot_profile(plot_type, d, cax=None, subcolumn=0, sigma=5, remove_bmol=True, vlim=None, vlog=None, zres=50, zlim=None, **opts): if plot_type == 'backscatter': cmap = copy.copy(mpl.cm.get_cmap('viridis')) under = '#222222' label = 'Att. vol. backscattering coef. (×10$^{-6}$ m$^{-1}$sr$^{-1}$)' if vlim is None: vlim = [0.1, 200] if vlog is None: vlog = True if len(d['backscatter'].shape) == 3: b = d['backscatter'][:, :, subcolumn] cloud_mask = d['cloud_mask'][:, :, subcolumn] bsd = d['backscatter_sd'][:,:,subcolumn] if 'backscatter_sd' in d \ else np.zeros(b.shape, dtype=np.float64) else: b = d['backscatter'] cloud_mask = d['cloud_mask'] bsd = d['backscatter_sd'] if 'backscatter_sd' in d \ else np.zeros(b.shape, dtype=np.float64) if sigma > 0: b -= sigma * bsd if remove_bmol and 'backscatter_mol' in d: bmol = d['backscatter_mol'] mask = ~np.isnan(bmol) b[mask] -= bmol[mask] x = b * 1e6 x[x <= 0.] = 0.5 * vlim[0] # A value below the limit. time = d['time'] zfull = d['zfull'] elif plot_type in ('clw', 'cli', 'cl'): cmap = copy.copy( mpl.cm.get_cmap({ 'clw': 'Reds', 'cli': 'Blues', 'cl': 'Greys_r', }[plot_type])) under = { 'clw': 'white', 'cli': 'white', 'cl': 'k', }[plot_type] label = { 'clw': 'Cloud water (g/kg)', 'cli': 'Cloud ice (g/kg)', 'cl': 'Cloud fraction (%)', }[plot_type] if vlim is None: vlim = { 'clw': [1e-3, 1], 'cli': [1e-3, 1], 'cl': [0, 100], }[plot_type] if vlog is None: vlog = {'clw': True, 'cli': True, 'cl': False}[plot_type] x = d[plot_type] if plot_type in ('clw', 'cli', 'clw+cli'): x *= 1e3 if x.shape == 3: x = x[:, :, subcolumn] if zlim is None: zlim = [np.min(d['zfull']), np.max(d['zfull'])] zhalf = np.arange(zlim[0], zlim[1] + zres, zres) zfull = 0.5 * (zhalf[1:] + zhalf[:-1]) xp = np.full((x.shape[0], len(zfull)), np.nan, np.float64) for i in range(xp.shape[0]): zhalfi = misc.half(d['zfull'][i, :]) xp[i, :] = algorithms.interp(zhalfi, x[i, :], zhalf) x = xp time = d['time'] else: raise ValueError('Invalid plot type "%s"' % plot_type) if vlog: norm = LogNorm(vlim[0], vlim[1]) else: norm = Normalize(vlim[0], vlim[1]) t1 = time[0] - 0.5 * (time[1] - time[0]) t2 = time[-1] + 0.5 * (time[-1] - time[-2]) z1 = zfull[0] - 0.5 * (zfull[1] - zfull[0]) z2 = zfull[-1] + 0.5 * (zfull[-1] - zfull[-2]) im = plt.imshow( x.T, extent=(t1, t2, z1 * 1e-3, z2 * 1e-3), aspect='auto', origin='lower', norm=norm, cmap=cmap, ) im.cmap.set_under(under) cb = plt.colorbar( cax=cax, label=label, pad=0.03, fraction=0.05, aspect='auto', extend='both', ) if zlim is not None: plt.ylim(zlim[0] * 1e-3, zlim[1] * 1e-3) plt.xlabel('Time (UTC)') plt.ylabel('Height (km)') formatter = plt.FuncFormatter(lambda t, p: \ aq.to_datetime(t).strftime('%d/%m\n%H:%M')) locator = AutoDateLocator() plt.gca().xaxis.set_major_formatter(formatter) plt.gca().xaxis.set_major_locator(locator) if plot_type == 'backscatter' and opts.get('cloud_mask'): cf = plt.contour( d['time'], d['zfull'] * 1e-3, cloud_mask.T, colors='red', linewidths=1, linestyles='dashed', levels=[-1., 0.5, 2.], ) plot_legend(handles=[ mlines.Line2D([], [], color='red', linestyle='dashed', label='Cloud mask') ], theme='dark') if 'altitude' in d: plt.plot(d['time'], d['altitude'] * 1e-3, color='red', lw=0.5)
def stats_map(d, state, tlim=None, blim=None, bres=None, bsd_lim=None, bsd_log=None, bsd_res=None, bsd_z=None, filter=None, zlim=None, zres=None, **kwargs): if zlim is not None and zres is not None: state['zfull2'] = state.get( 'zfull2', np.arange(zlim[0] + 0.5 * zres, zlim[1], zres)) else: state['zfull2'] = state.get('zfull2', d['zfull']) zhalf = misc.half(d['zfull']) zhalf2 = misc.half(state['zfull2']) state['backscatter_half'] = state.get( 'backscatter_half', np.arange(blim[0], blim[1] + bres, bres)) state['backscatter_full'] = state.get( 'backscatter_full', 0.5 * (state['backscatter_half'][1:] + state['backscatter_half'][:-1])) o = len(state['backscatter_full']) state['backscatter_sd_half'] = state.get('backscatter_sd_half', np.exp(np.arange(np.log(bsd_lim[0]), np.log(bsd_lim[1] + bsd_res), np.log(bsd_lim[0] + bsd_res) - np.log(bsd_lim[0]))) if bsd_log is True \ else np.arange(bsd_lim[0], bsd_lim[1] + bsd_res, bsd_res) ) state['backscatter_sd_full'] = state.get( 'backscatter_sd_full', 0.5 * (state['backscatter_sd_half'][1:] + state['backscatter_sd_half'][:-1])) osd = len(state['backscatter_sd_full']) m2 = len(state['zfull2']) if len(d['cloud_mask'].shape) == 3: n, m, l = d['cloud_mask'].shape dims = (m, l) dims2 = (m2, l) hist_dims = (o, m, l) hist_dims2 = (o, m2, l) sd_hist_dims = (osd, l) filter_mask_dims = (n, l) else: n, m = d['cloud_mask'].shape l = 0 dims = (m, ) dims2 = (m2, ) hist_dims = (o, m) hist_dims2 = (o, m2) sd_hist_dims = (osd, ) filter_mask_dims = (n, ) state['n'] = state.get('n', 0 if l == 0 else np.zeros(l, dtype=np.int64)) state['backscatter_avg'] = state.get('backscatter_avg', np.zeros(dims2, dtype=np.float64)) state['backscatter_mol_avg'] = state.get('backscatter_mol_avg', np.zeros(dims2, dtype=np.float64)) state['cl'] = state.get('cl', np.zeros(dims2, dtype=np.float64)) state['clt'] = state.get('clt', np.zeros(l, dtype=np.float64) if l > 0 else 0) state['backscatter_hist'] = state.get( 'backscatter_hist', np.zeros(hist_dims2, dtype=np.float64)) state['backscatter_sd_hist'] = state.get( 'backscatter_sd_hist', np.zeros(sd_hist_dims, dtype=np.float64)) backscatter_hist_tmp = np.zeros(hist_dims, dtype=np.float64) cl_tmp = np.zeros(dims, dtype=np.float64) clt_tmp = np.zeros(l, dtype=np.float64) if l > 0 else 0 backscatter_avg_tmp = np.zeros(dims, dtype=np.float64) backscatter_mol_avg_tmp = np.zeros(dims, dtype=np.float64) if tlim is not None: mask = (d['time'] >= tlim[0]) & (d['time'] < tlim[1]) else: mask = np.ones(n, dtype=np.bool) if l > 0: mask &= np.all(~np.isnan(d['backscatter']), axis=(1, 2)) else: mask &= np.all(~np.isnan(d['backscatter']), axis=(1, )) filter_mask = np.ones(filter_mask_dims, dtype=np.bool) if 'cloudy' in filter: filter_mask &= np.any(d['cloud_mask'], axis=1) if 'clear' in filter: filter_mask &= ~np.any(d['cloud_mask'], axis=1) if 'day' in filter: filter_mask_0 = misc.sun_altitude(d['time'], d['lon'], d['lat']) >= 0 if l > 0: filter_mask_0 = np.tile(filter_mask_0, [l, 1]).T filter_mask &= filter_mask_0 if 'night' in filter: filter_mask_0 = misc.sun_altitude(d['time'], d['lon'], d['lat']) < 0 if l > 0: filter_mask_0 = np.tile(filter_mask_0, [l, 1]).T filter_mask &= filter_mask_0 if not np.any(mask): return for j in range(m): if l > 0: for k in range(l): backscatter_hist_tmp[:, j, k] += np.histogram( d['backscatter'][filter_mask[:, k] & mask, j, k], bins=state['backscatter_half'])[0] else: backscatter_hist_tmp[:, j] += np.histogram( d['backscatter'][filter_mask & mask, j], bins=state['backscatter_half'])[0] jsd = np.argmin(np.abs(d['zfull'] - bsd_z)) state['backscatter_sd_z'] = d['zfull'][jsd] if 'backscatter_sd' in d: if l > 0: for k in range(l): state['backscatter_sd_hist'][:, k] += np.histogram( d['backscatter_sd'][filter_mask[:, k] & mask, jsd, k], bins=state['backscatter_sd_half'])[0] else: state['backscatter_sd_hist'] += np.histogram( d['backscatter_sd'][filter_mask & mask, jsd], bins=state['backscatter_sd_half'])[0] for i in range(o): if l > 0: for k in range(l): state['backscatter_hist'][i, :, k] += interp( zhalf, backscatter_hist_tmp[i, :, k], zhalf2) else: state['backscatter_hist'][i, :] += interp( zhalf, backscatter_hist_tmp[i, :], zhalf2) for i in range(n): if not mask[i]: continue if l > 0: for k in range(l): if not filter_mask[i, k]: continue cl_tmp[:, k] += d['cloud_mask'][i, :, k] backscatter_avg_tmp[:, k] += d['backscatter'][i, :, k] if 'backscatter_mol' in d: backscatter_mol_avg_tmp[:, k] += d['backscatter_mol'][i, :] state['n'][k] += 1 state['clt'][k] += np.any(d['cloud_mask'][i, :, k]) else: if not filter_mask[i]: continue cl_tmp[:] += d['cloud_mask'][i, :] backscatter_avg_tmp[:] += d['backscatter'][i, :] if 'backscatter_mol' in d: backscatter_mol_avg_tmp[:] += d['backscatter_mol'][i, :] state['n'] += 1 state['clt'] += np.any(d['cloud_mask'][i, :]) if l > 0: for k in range(l): state['cl'][:, k] += interp(zhalf, cl_tmp[:, k], zhalf2) state['backscatter_avg'][:, k] += interp(zhalf, backscatter_avg_tmp[:, k], zhalf2) state['backscatter_mol_avg'][:, k] += interp( zhalf, backscatter_mol_avg_tmp[:, k], zhalf2) else: state['cl'] += interp(zhalf, cl_tmp, zhalf2) state['backscatter_avg'] += interp(zhalf, backscatter_avg_tmp, zhalf2) state['backscatter_mol_avg'] += interp(zhalf, backscatter_mol_avg_tmp, zhalf2)