def _prepare_default_regions_json(): regs = {} for regname in get_all_default_region_ids(): reg = Region(regname) regs[regname] = r = {} latr = reg.lat_range r['minLat'] = latr[0] r['maxLat'] = latr[1] lonr = reg.lon_range r['minLon'] = lonr[0] r['maxLon'] = lonr[1] return regs
def set_region(self, region): if isinstance(region, str): region = Region(region) if not isinstance(region, Region): raise IOError('Invalid input for region, need string or ' 'instance of Region class, got {}'.format(region)) self.lon_range = region.lon_range self.lat_range = region.lat_range self._region = region spl = self.name.split('-') self._name = '{}-{}'.format(region.name, spl[1])
def plot_map_aerocom(data, region=None, fig=None, **kwargs): """High level map plotting function for Aerocom default plotting Note ---- This function does not iterate over a cube in time, but uses the first available time index in the data. Parameters ---------- data : :obj:`GriddedData` input data from one timestamp (if data contains more than one time stamp, the first index is used) TODO finish docstring """ #kwargs["fix_aspect"] = 1.6 from pyaerocom import GriddedData if not isinstance(data, GriddedData): raise TypeError("This plotting method needs an instance of pyaerocom " "GriddedData on input, got: %s" % type(data)) if region: if isinstance(region, str): region = Region(region) if not isinstance(region, Region): raise TypeError( "Invalid input for region, need None, str or Region") data = data.crop(region=region) if not data.suppl_info["region"]: data = data.crop(region="WORLD") region = data.suppl_info["region"] s = data.plot_settings fig = plot_griddeddata_on_map(data, xlim=region.lon_range_plot, ylim=region.lat_range_plot, vmin=s.map_vmin, vmax=s.map_vmax, c_over=s.map_c_over, c_under=s.map_c_under, cbar_levels=s.map_cbar_levels, xticks=region.lon_ticks, yticks=region.lat_ticks, cbar_ticks=s.map_cbar_ticks, **kwargs) ax = fig.axes[0] # annotate model in lower left corner lonr, latr = region.lon_range_plot, region.lat_range_plot ax.annotate(data.name, xy=(lonr[0] + (lonr[1] - lonr[0]) * .03, latr[0] + (latr[1] - latr[0]) * .03), xycoords='data', horizontalalignment='left', color='black', fontsize=MPL_PARAMS['axes.titlesize'] + 2, bbox=dict(boxstyle='square', facecolor='white', edgecolor='none', alpha=0.7)) ax.annotate('source: AEROCOM', xy=(0.97, 0.03), xycoords='figure fraction', horizontalalignment='right', fontsize=MPL_PARAMS['xtick.labelsize'], bbox=dict(boxstyle='square', facecolor='none', edgecolor='black')) ax.set_title("{} {} mean {:.3f}".format( data.var_name.upper(), to_datetime(data.start).strftime("%Y%m%d"), data.area_weighted_mean())) return fig
def apply_latlon_filter(self, lat_range=None, lon_range=None, region_id=None, inplace=False): """Apply regional filter Returns new object filtered for input coordinate range Parameters ---------- lat_range : list, optional latitude range that is supposed to be applied. If specified, then also lon_range need to be specified, else, region_id is checked against AeroCom default regions (and used if applicable) lon_range : list, optional longitude range that is supposed to be applied. If specified, then also lat_range need to be specified, else, region_id is checked against AeroCom default regions (and used if applicable) region_id : str name of region to be applied. If provided (i.e. not None) then input args `lat_range` and `lon_range` are ignored Returns ------- ColocatedData filtered data object """ is_2d = self._check_latlon_coords() if region_id is not None: reg = Region(region_id) lon_range = reg.lon_range lat_range = reg.lat_range region_id = reg.name if all([x is None for x in (lat_range, lon_range)]): raise ValueError('Please provide input, either for lat_range or ' 'lon_range or region_id') if lon_range is None: lon_range = [-180, 180] if lat_range is None: lat_range = [-90, 90] latr, lonr = self.data.attrs['lat_range'], self.data.attrs['lon_range'] if np.equal(latr, lat_range).all() and np.equal(lonr, lon_range).all(): const.print_log.info('Filtering of lat_range={} and lon_range={} ' 'results in unchanged object, returning self' .format(lon_range, lat_range)) return self if lat_range[0] < latr[0]: lat_range[0] = latr[0] if lat_range[1] > latr[1]: lat_range[1] = latr[1] if lon_range[0] < lonr[0]: lon_range[0] = lonr[0] if lon_range[1] > lonr[1]: lon_range[1] = lonr[1] if is_2d: filtered = self._filter_latlon_2d(self.data, lat_range, lon_range) else: filtered = self._filter_latlon_3d(self.data, lat_range, lon_range) if not isinstance(region_id, str): region_id = 'CUSTOM' try: alt_info = filtered.attrs['filter_name'].split('-', 1)[-1] except Exception: alt_info = 'CUSTOM' filtered.attrs['filter_name'] = '{}-{}'.format(region_id, alt_info) filtered.attrs['region'] = region_id filtered.attrs['lon_range'] = lon_range filtered.attrs['lat_range'] = lat_range if inplace: self.data = filtered return self return ColocatedData(filtered)
def apply_latlon_filter(self, lat_range=None, lon_range=None, region_id=None): """Apply regional filter Returns new object filtered for input coordinate range Parameters ---------- lat_range : list, optional latitude range that is supposed to be applied. If specified, then also lon_range need to be specified, else, region_id is checked against AeroCom default regions (and used if applicable) lon_range : list, optional longitude range that is supposed to be applied. If specified, then also lat_range need to be specified, else, region_id is checked against AeroCom default regions (and used if applicable) region_id : str name of region to be applied Returns ------- ColocatedData filtered data object """ is_2d = self._check_latlon_coords() if valid_region(region_id): reg = Region(region_id) if lon_range is not None and lon_range != reg.lon_range: raise ValueError('Conflict: receieved region ID {}, which has ' 'a different longitude range ({}) than input ' 'lon_range {}'.format(region_id, reg.lon_range, lon_range)) if lat_range is not None and lat_range != reg.lat_range: raise ValueError('Conflict: receieved region ID {}, which has ' 'a different longitude range ({}) than input ' 'lat_range {}'.format(region_id, reg.lat_range, lat_range)) lon_range = reg.lon_range lat_range = reg.lat_range region_id = reg.name if lon_range is None and lat_range is None: raise ValueError('Need either lon_range or lat_range or valid ' 'region_id') if lon_range is None: lon_range = [-180, 180] if lat_range is None: lat_range = [-90, 90] latr, lonr = self.data.attrs['lat_range'], self.data.attrs['lon_range'] if np.equal(latr, lat_range).all() and np.equal(lonr, lon_range).all(): const.print_log.info( 'Filtering of lat_range={} and lon_range={} ' 'results in unchanged object, returning self'.format( lon_range, lat_range)) return self if lat_range[0] < latr[0]: lat_range[0] = latr[0] if lat_range[1] > latr[1]: lat_range[1] = latr[1] if lon_range[0] < lonr[0]: lon_range[0] = lonr[0] if lon_range[1] > lonr[1]: lon_range[1] = lonr[1] if is_2d: filtered = self._filter_latlon_2d(lat_range, lon_range) else: filtered = self._filter_latlon_3d(lat_range, lon_range) if not isinstance(region_id, str): region_id = 'CUSTOM' try: alt_info = filtered.attrs['filter_name'].split('-', 1)[-1] except: alt_info = 'CUSTOM' filtered.attrs['filter_name'] = '{}-{}'.format(region_id, alt_info) filtered.attrs['region'] = region_id filtered.attrs['lon_range'] = lon_range filtered.attrs['lat_range'] = lat_range return ColocatedData(filtered)
def region(self): """Region associated with this filter (instance of :class:`Region`)""" r = self._region if not isinstance(r, Region) or not r.name == self.region_name: self._region = Region(self.region_name) return self._region