def coloc_mod_on_pro(self, model, profiles, varnames, select=None, method='nearest'): '''Colocalize model on profile data. Load model data corresponding to the selected profiles positions and time. Returns loaded model longitudes, latitudes, depths and requested variable(s) :Params: - **model**: model data :class:`~vacumm.data.misc.dataset.Dataset` - **profiles**: profile data :class:`~vacumm.data.misc.profile.ProfilesDataset` - **varnames**: variables to load (ex: ('temp','sal') or (('temp','temperature'),('sal','salinity')) - **select**: selector - **method**: coloc method (**nearest** or **interp**) :Return: - **lons_mod**: model longitude coordinates, shape: (profile) - **lats_mod**: model latitude coordinates, shape: (profile) - **deps_mod**: model depth coordinates, shape: (level,profile) - **var1**: requested variables, shape: (level,profile) - ... - **varN** .. todo:: - also load and return profile data here - exclude coords where profile data is masked (no data for specified depth) - return time coordinates - return depth and vars with shape (profile,level) ''' self.verbose( 'Colocalizing %s on %s\nvarnames: %s\nselect: %s\n method: %s', model.__class__.__name__, profiles.__class__.__name__, varnames, select, method) prof_pro = profiles.get_axis('profile', select=select) if prof_pro is None or not len(prof_pro): raise Exception('No profiles found, aborting') lev_pro = profiles.get_axis('level', select=select) time_pro = profiles.get_variable('time', select=select) lons_pro = profiles.get_variable('longitude', select=select) lats_pro = profiles.get_variable('latitude', select=select) dates = create_time(time_pro).asComponentTime() self.info('Number of profiles: %s', len(dates)) self.info('Profiles time coverage: %s to %s', dates[0], dates[-1]) # Init model td = model.get_time_res() dtmax = (td.days * 86400 + td.seconds, 'seconds') self.info('Detected model time step: %s', td) grid_mod = model.get_grid() xres, yres = resol(grid_mod) time_mod = model.get_time() ctime_mod = time_mod.asComponentTime() self.info('Model time coverage: %s to %s', ctime_mod[0], ctime_mod[-1]) level_mod = model.get_level(select=select) lons_mod = MV2.zeros((len(prof_pro), )) + MV2.masked lats_mod = lons_mod.clone() deps_mod = MV2.zeros((len(level_mod), len(prof_pro))) + MV2.masked deps_mod.setAxis(1, prof_pro) lons_mod.id, lats_mod.id, deps_mod.id = 'longitude', 'latitude', 'depth' # Creation des variables demandees variables = [] for n in varnames: v = MV2.zeros((len(level_mod), len(prof_pro))) + MV2.masked v.setAxis(1, prof_pro) v.id = is_iterable(n) and n[0] or n variables.append(v) cdms2.setAutoBounds(1) # ??? # Boucle temporelle for ip, date in enumerate(dates): try: # Limites spatiales lon = lons_pro[ip] lat = lats_pro[ip] lon_min = lon - 2 * xres lon_max = lon + 2 * xres lat_min = lat - 2 * yres lat_max = lat + 2 * yres date_interval = (add_time(date, -dtmax[0], dtmax[1]), add_time(date, dtmax[0], dtmax[1]), 'ccb') self.info('Colocalizing data for date %s, lon: %s, lat: %s', date, lon, lat) # Methode 1 : donnees les plus proches if method == 'nearest': sel = dict(time=(date, date, 'ccb'), longitude=(lon, lon, 'ccb'), latitude=(lat, lat, 'ccb')) # Verifier la disponibilite des donnees if time_mod.mapIntervalExt(sel['time']) is None: self.warning('Time interval %s not found', sel['time']) continue if grid_mod.getLatitude().mapInterval( sel['latitude']) is None: self.warning('Latitude coordinate %s not found', sel['latitude']) continue if grid_mod.getLongitude().mapInterval( sel['longitude']) is None: self.warning('Longitude coordinate %s not found', sel['longitude']) continue # Load tmp depth to get lon & lat coordinates #tmp = model.get_depth(select=sel, squeeze=False) # tmp squeezed !!! see sigma ? tmp = model.get_variable(varnames[0], select=sel, squeeze=False) lons_mod[ip] = tmp.getLongitude()[0] lats_mod[ip] = tmp.getLatitude()[0] deps_mod[:, ip] = model.get_depth(select=sel, squeeze=True) for iv, vn in enumerate(varnames): variables[iv][:, ip] = model.get_variable(vn, select=sel, squeeze=True) # Methode 2 : interpolation elif method == 'interp': sel = dict(time=date_interval, longitude=(lon_min, lon_max), latitude=(lat_min, lat_max)) if time_mod.mapIntervalExt(sel['time']) is None: self.warning('Time interval %s not found', sel['time']) continue if grid_mod.getLatitude().mapInterval( sel['latitude']) is None: self.warning('Latitude coordinate %s not found', sel['latitude']) continue if grid_mod.getLongitude().mapInterval( sel['longitude']) is None: self.warning('Longitude coordinate %s not found', sel['longitude']) continue # Lectures order = 'tzyx' # lon & lat du profile car interp sur cette position lons_mod[ip], lats_mod[ip] = lon, lat deps_mod_tzyx = model.get_depth(select=sel, order=order, squeeze=True) tmp_tzyx = [] for iv, vn in enumerate(varnames): tmp_tzyx.append( model.get_variable(vn, select=sel, order=order, squeeze=True)) # Interpolations temporelles mctime = tmp_tzyx[0].getTime() mrtime = mctime.asRelativeTime() d0 = date.torel(mctime.units).value - mrtime[0].value d1 = mrtime[1].value - date.torel(mctime.units).value f0 = d0 / (d0 + d1) f1 = d1 / (d0 + d1) deps_mod_zyx = f0 * deps_mod_tzyx[0] + f1 * deps_mod_tzyx[1] tmp_zyx = [] for iv, vn in enumerate(varnames): tmp_zyx.append(f0 * tmp_tzyx[iv][0] + f1 * tmp_tzyx[iv][1]) del tmp_tzyx # Interpolations spatiales deps_mod[:, ip] = numpy.squeeze( grid2xy(deps_mod_zyx, numpy.array([lon]), numpy.array([lat]), method='nat')) for iv, vn in enumerate(varnames): variables[iv][:, ip] = numpy.squeeze( grid2xy(tmp_zyx[iv], numpy.array([lon]), numpy.array([lat]), method='nat')) del tmp_zyx else: raise ValueError('Invalid colocation method: %s' % (method)) except: self.exception('Failed to colocalize data for date %s', date) for v in [deps_mod] + variables: v.getAxis(0).id = 'level' v.getAxis(0).designateLevel() data = tuple([lons_mod, lats_mod, deps_mod] + variables) self.verbose('Colocalized data:\n %s', '\n '.join(self.describe(o) for o in data)) return data
def coloc_mod_on_pro(self, model, profiles, varnames, select=None, method='nearest'): '''Colocalize model on profile data. Load model data corresponding to the selected profiles positions and time. Returns loaded model longitudes, latitudes, depths and requested variable(s) :Params: - **model**: model data :class:`~vacumm.data.misc.dataset.Dataset` - **profiles**: profile data :class:`~vacumm.data.misc.profile.ProfilesDataset` - **varnames**: variables to load (ex: ('temp','sal') or (('temp','temperature'),('sal','salinity')) - **select**: selector - **method**: coloc method (**nearest** or **interp**) :Return: - **lons_mod**: model longitude coordinates, shape: (profile) - **lats_mod**: model latitude coordinates, shape: (profile) - **deps_mod**: model depth coordinates, shape: (level,profile) - **var1**: requested variables, shape: (level,profile) - ... - **varN** .. todo:: - also load and return profile data here - exclude coords where profile data is masked (no data for specified depth) - return time coordinates - return depth and vars with shape (profile,level) ''' self.verbose('Colocalizing %s on %s\nvarnames: %s\nselect: %s\n method: %s', model.__class__.__name__, profiles.__class__.__name__, varnames, select, method) prof_pro = profiles.get_axis('profile', select=select) if prof_pro is None or not len(prof_pro): raise Exception('No profiles found, aborting') lev_pro = profiles.get_axis('level', select=select) time_pro = profiles.get_variable('time', select=select) lons_pro = profiles.get_variable('longitude', select=select) lats_pro = profiles.get_variable('latitude', select=select) dates = create_time(time_pro).asComponentTime() self.info('Number of profiles: %s', len(dates)) self.info('Profiles time coverage: %s to %s', dates[0], dates[-1]) # Init model td = model.get_time_res() dtmax = (td.days*86400+td.seconds, 'seconds') self.info('Detected model time step: %s', td) grid_mod = model.get_grid() xres, yres = resol(grid_mod) time_mod = model.get_time() ctime_mod = time_mod.asComponentTime() self.info('Model time coverage: %s to %s', ctime_mod[0], ctime_mod[-1]) level_mod = model.get_level(select=select) lons_mod = MV2.zeros((len(prof_pro),))+MV2.masked lats_mod = lons_mod.clone() deps_mod = MV2.zeros((len(level_mod), len(prof_pro)))+MV2.masked deps_mod.setAxis(1, prof_pro) lons_mod.id, lats_mod.id, deps_mod.id = 'longitude', 'latitude', 'depth' # Creation des variables demandees variables = [] for n in varnames: v = MV2.zeros((len(level_mod), len(prof_pro)))+MV2.masked v.setAxis(1, prof_pro) v.id = is_iterable(n) and n[0] or n variables.append(v) cdms2.setAutoBounds(1) # ??? # Boucle temporelle for ip, date in enumerate(dates): try: # Limites spatiales lon = lons_pro[ip] lat = lats_pro[ip] lon_min = lon-2*xres lon_max = lon+2*xres lat_min = lat-2*yres lat_max = lat+2*yres date_interval = (add_time(date, - dtmax[0], dtmax[1]), add_time(date, dtmax[0], dtmax[1]), 'ccb') self.info('Colocalizing data for date %s, lon: %s, lat: %s', date, lon, lat) # Methode 1 : donnees les plus proches if method == 'nearest': sel = dict(time=(date, date, 'ccb'), longitude=(lon, lon, 'ccb'), latitude=(lat, lat, 'ccb')) # Verifier la disponibilite des donnees if time_mod.mapIntervalExt(sel['time']) is None: self.warning('Time interval %s not found', sel['time']) continue if grid_mod.getLatitude().mapInterval(sel['latitude']) is None: self.warning('Latitude coordinate %s not found', sel['latitude']) continue if grid_mod.getLongitude().mapInterval(sel['longitude']) is None: self.warning('Longitude coordinate %s not found', sel['longitude']) continue # Load tmp depth to get lon & lat coordinates #tmp = model.get_depth(select=sel, squeeze=False) # tmp squeezed !!! see sigma ? tmp = model.get_variable(varnames[0], select=sel, squeeze=False) lons_mod[ip] = tmp.getLongitude()[0] lats_mod[ip] = tmp.getLatitude()[0] deps_mod[:, ip] = model.get_depth(select=sel, squeeze=True) for iv,vn in enumerate(varnames): variables[iv][:,ip] = model.get_variable(vn, select=sel, squeeze=True) # Methode 2 : interpolation elif method == 'interp': sel = dict(time=date_interval, longitude=(lon_min, lon_max), latitude=(lat_min, lat_max)) if time_mod.mapIntervalExt(sel['time']) is None: self.warning('Time interval %s not found', sel['time']) continue if grid_mod.getLatitude().mapInterval(sel['latitude']) is None: self.warning('Latitude coordinate %s not found', sel['latitude']) continue if grid_mod.getLongitude().mapInterval(sel['longitude']) is None: self.warning('Longitude coordinate %s not found', sel['longitude']) continue # Lectures order = 'tzyx' # lon & lat du profile car interp sur cette position lons_mod[ip], lats_mod[ip] = lon, lat deps_mod_tzyx = model.get_depth(select=sel, order=order, squeeze=True) tmp_tzyx = [] for iv,vn in enumerate(varnames): tmp_tzyx.append(model.get_variable(vn, select=sel, order=order, squeeze=True)) # Interpolations temporelles mctime = tmp_tzyx[0].getTime() mrtime = mctime.asRelativeTime() d0 = date.torel(mctime.units).value - mrtime[0].value d1 = mrtime[1].value - date.torel(mctime.units).value f0 = d0 / (d0 + d1) f1 = d1 / (d0 + d1) deps_mod_zyx = f0 * deps_mod_tzyx[0] + f1 * deps_mod_tzyx[1] tmp_zyx = [] for iv,vn in enumerate(varnames): tmp_zyx.append(f0 * tmp_tzyx[iv][0] + f1 * tmp_tzyx[iv][1]) del tmp_tzyx # Interpolations spatiales deps_mod[:,ip] = numpy.squeeze(grid2xy(deps_mod_zyx, numpy.array([lon]), numpy.array([lat]), method='nat')) for iv,vn in enumerate(varnames): variables[iv][:,ip] = numpy.squeeze(grid2xy(tmp_zyx[iv], numpy.array([lon]), numpy.array([lat]), method='nat')) del tmp_zyx else: raise ValueError('Invalid colocation method: %s'%(method)) except: self.exception('Failed to colocalize data for date %s', date) for v in [deps_mod] + variables: v.getAxis(0).id = 'level' v.getAxis(0).designateLevel() data = tuple([lons_mod, lats_mod, deps_mod] + variables) self.verbose('Colocalized data:\n %s', '\n '.join(self.describe(o) for o in data)) return data
def plot_layer_mod_on_pro(self, model, profiles, varname, depth, select=None, **kwargs): '''Get a layer of variable for a specified depth. :Params: - **varname**: variable to process - **depth**: output depth(s) Other params, see: :func:`coloc_mod_on_pro` ''' self.verbose( 'Plotting layer of colocalized %s on %s\nvarname: %s\ndepth: %s\nselect: %s\nkwargs: %s', model.__class__.__name__, profiles.__class__.__name__, varname, depth, select, kwargs) lons_mod, lats_mod, deps_mod, var_mod = \ self.coloc_mod_on_pro( model, profiles, # If varname is a list of possible names, wrap it into a # tuple of one element as we are requiring only one variable len(numpy.shape(varname)) and (varname,) or varname, select, **kwargs) odep = create_dep(is_iterable(depth) and depth or [depth]) var_mod = var_mod.reorder('-z') var_mod = interp1d(var_mod, axo=odep, xmap=0, xmapper=deps_mod) # Required order: ...z var_mod = var_mod.reorder('z-') model.verbose('layer: %s', var_mod) lons_pro, lats_pro, var_pro = profiles.get_layer(varname, depth, select=select) profiles.verbose('layer: %s', var_pro) # ===== # Tracés vmin = var_pro.min() vmax = var_pro.max() if var_mod.count(): vmin = min(var_mod.min(), vmin) vmax = max(var_mod.max(), vmax) else: self.warning('No model data') if 'latitude' in select: lat_min, lat_max = select['latitude'][:2] else: la = model.get_latitude() lat_min, lat_max = min(la), max(la) if 'longitude' in select: lon_min, lon_max = select['longitude'][:2] else: lo = model.get_longitude() lon_min, lon_max = min(lo), max(lo) levels = auto_scale((vmin, vmax)) vmin = levels[0] vmax = levels[-1] # Création de la palette cmap = cmap_magic(levels) # On trace de champ du modèle moyené sur la période choisie m = map2(lon=(lon_min, lon_max), lat=(lat_min, lat_max), show=False) # On trace le modèle en fond # ===== msca = None try: msca = m.map.scatter(lons_mod, lats_mod, s=100, c=var_mod, vmin=vmin, vmax=vmax, cmap=cmap, label='model') except: self.exception('Failed plotting model data') # ===== # Triangulation du modèle # import matplotlib.tri as tri # triang = tri.Triangulation(lons_mod, lats_mod) # # On trace le modèle en fond # mod = m.axes.tripcolor(triang, var_mod, vmin=vmin, vmax=vmax, cmap=cmap) # ===== # On trace les observations avec des points plus petits psca = None try: psca = m.map.scatter(lons_pro, lats_pro, s=25, c=var_pro, vmin=m.vmin, vmax=m.vmax, cmap=m.cmap, label='profiles') except: self.exception('Failed plotting profile data') # Colorbar if msca is not None: colorbar(msca) elif psca is not None: colorbar(psca)
def plot_layer_mod_on_pro(self, model, profiles, varname, depth, select=None, **kwargs): '''Get a layer of variable for a specified depth. :Params: - **varname**: variable to process - **depth**: output depth(s) Other params, see: :func:`coloc_mod_on_pro` ''' self.verbose('Plotting layer of colocalized %s on %s\nvarname: %s\ndepth: %s\nselect: %s\nkwargs: %s', model.__class__.__name__, profiles.__class__.__name__, varname, depth, select, kwargs) lons_mod, lats_mod, deps_mod, var_mod = \ self.coloc_mod_on_pro( model, profiles, # If varname is a list of possible names, wrap it into a # tuple of one element as we are requiring only one variable len(numpy.shape(varname)) and (varname,) or varname, select, **kwargs) odep = create_dep(is_iterable(depth) and depth or [depth]) var_mod = var_mod.reorder('-z') var_mod = interp1d(var_mod, axo=odep, xmap=0, xmapper=deps_mod) # Required order: ...z var_mod = var_mod.reorder('z-') model.verbose('layer: %s', var_mod) lons_pro, lats_pro, var_pro = profiles.get_layer(varname, depth, select=select) profiles.verbose('layer: %s', var_pro) # ===== # Tracés vmin = var_pro.min() vmax = var_pro.max() if var_mod.count(): vmin = min(var_mod.min(), vmin) vmax = max(var_mod.max(), vmax) else: self.warning('No model data') if 'latitude' in select: lat_min, lat_max = select['latitude'][:2] else: la = model.get_latitude() lat_min, lat_max = min(la), max(la) if 'longitude' in select: lon_min, lon_max = select['longitude'][:2] else: lo = model.get_longitude() lon_min, lon_max = min(lo), max(lo) levels = auto_scale((vmin, vmax)) vmin = levels[0] vmax = levels[-1] # Création de la palette cmap = cmap_magic(levels) # On trace de champ du modèle moyené sur la période choisie m = map2(lon=(lon_min, lon_max), lat=(lat_min, lat_max), show=False) # On trace le modèle en fond # ===== msca = None try: msca = m.map.scatter(lons_mod, lats_mod, s=100, c=var_mod, vmin=vmin, vmax=vmax, cmap=cmap, label='model') except: self.exception('Failed plotting model data') # ===== # Triangulation du modèle # import matplotlib.tri as tri # triang = tri.Triangulation(lons_mod, lats_mod) # # On trace le modèle en fond # mod = m.axes.tripcolor(triang, var_mod, vmin=vmin, vmax=vmax, cmap=cmap) # ===== # On trace les observations avec des points plus petits psca = None try: psca = m.map.scatter(lons_pro, lats_pro, s=25, c=var_pro, vmin=m.vmin, vmax=m.vmax, cmap=m.cmap, label='profiles') except: self.exception('Failed plotting profile data') # Colorbar if msca is not None: colorbar(msca) elif psca is not None: colorbar(psca)