Source code for nes.nc_projections.points_nes_ghost

#!/usr/bin/env python

import sys
from warnings import warn
from numpy import float64, empty, ndarray, generic, array, issubdtype, character, concatenate, int64
from netCDF4 import date2num
from copy import deepcopy
from .points_nes import PointsNes


[docs] class PointsNesGHOST(PointsNes): """ Attributes ---------- _qa : dict Quality flags (GHOST checks) dictionary with the complete "data" key for all the values and the rest of the attributes. _flag : dict Data flags (given by data provider) dictionary with the complete "data" key for all the values and the rest of the attributes. _qa : dict Quality flags (GHOST checks) dictionary with the portion of "data" corresponding to the rank values. _flag : dict Data flags (given by data provider) dictionary with the portion of "data" corresponding to the rank values. """ def __init__(self, comm=None, path=None, info=False, dataset=None, parallel_method="X", avoid_first_hours=0, avoid_last_hours=0, first_level=0, last_level=None, create_nes=False, balanced=False, times=None, **kwargs): """ Initialize the PointsNesGHOST class. Parameters ---------- comm: MPI.COMM MPI Communicator. path: str Path to the NetCDF to initialize the object. info: bool Indicates if you want to get reading/writing info. dataset: Dataset NetCDF4-python Dataset to initialize the class. parallel_method : str Indicates the parallelization method that you want. Default: "X". Accepted values: ["X"]. avoid_first_hours : int Number of hours to remove from first time steps. avoid_last_hours : int Number of hours to remove from last time steps. first_level : int Index of the first level to use. last_level : int, None Index of the last level to use. None if it is the last. create_nes : bool Indicates if you want to create the object from scratch (True) or through an existing file. balanced : bool Indicates if you want a balanced parallelization or not. Balanced dataset cannot be written in chunking mode. times : list, None List of times to substitute the current ones while creation. """ super(PointsNesGHOST, self).__init__(comm=comm, path=path, info=info, dataset=dataset, parallel_method=parallel_method, avoid_first_hours=avoid_first_hours, avoid_last_hours=avoid_last_hours, first_level=first_level, last_level=last_level, create_nes=create_nes, times=times, balanced=balanced, **kwargs) # Complete dimensions self._flag = self._get_coordinate_dimension(["flag"]) self._qa = self._get_coordinate_dimension(["qa"]) # Dimensions screening self.flag = self._get_coordinate_values(self._flag, "X") self.qa = self._get_coordinate_values(self._qa, "X")
[docs] @staticmethod def new(comm=None, path=None, info=False, dataset=None, parallel_method="X", avoid_first_hours=0, avoid_last_hours=0, first_level=0, last_level=None, create_nes=False, balanced=False, times=None, **kwargs): """ Initialize the PointsNesGHOST class. Parameters ---------- comm: MPI.COMM MPI Communicator. path: str Path to the NetCDF to initialize the object. info: bool Indicates if you want to get reading/writing info. dataset: Dataset NetCDF4-python Dataset to initialize the class. parallel_method : str Indicates the parallelization method that you want. Default: "X". Accepted values: ["X"]. avoid_first_hours : int Number of hours to remove from first time steps. avoid_last_hours : int Number of hours to remove from last time steps. first_level : int Index of the first level to use. last_level : int, None Index of the last level to use. None if it is the last. create_nes : bool Indicates if you want to create the object from scratch (True) or through an existing file. balanced : bool Indicates if you want a balanced parallelization or not. Balanced dataset cannot be written in chunking mode. times : list, None List of times to substitute the current ones while creation. """ new = PointsNesGHOST(comm=comm, path=path, info=info, dataset=dataset, parallel_method=parallel_method, avoid_first_hours=avoid_first_hours, avoid_last_hours=avoid_last_hours, first_level=first_level, last_level=last_level, create_nes=create_nes, balanced=balanced, times=times, **kwargs) return new
def _create_dimensions(self, netcdf): """ Create "N_flag_codes" and "N_qa_codes" dimensions and the super dimensions "time", "time_nv", "station", and "strlen". Parameters ---------- netcdf : Dataset NetCDF object. """ super(PointsNesGHOST, self)._create_dimensions(netcdf) # Create N_flag_codes and N_qa_codes dimensions netcdf.createDimension("N_flag_codes", self._flag["data"].shape[2]) netcdf.createDimension("N_qa_codes", self._qa["data"].shape[2]) return None # noinspection DuplicatedCode def _create_dimension_variables(self, netcdf): """ Create the "time", "time_bnds", "station", "lat", "lat_bnds", "lon" and "lon_bnds" variables. Parameters ---------- netcdf : Dataset NetCDF object. """ # TIMES time_var = netcdf.createVariable("time", float64, ("time",), zlib=self.zip_lvl > 0, complevel=self.zip_lvl) time_var.units = "hours since {0}".format( self.get_full_times()[self._get_time_id(self.hours_start, first=True)].strftime("%Y-%m-%d %H:%M:%S")) time_var.standard_name = "time" time_var.calendar = "standard" time_var.long_name = "time" if self.time_bnds is not None: time_var.bounds = "time_bnds" if self.size > 1: time_var.set_collective(True) time_var[:] = date2num(self.get_full_times()[self._get_time_id(self.hours_start, first=True): self._get_time_id(self.hours_end, first=False)], time_var.units, time_var.calendar) # TIME BOUNDS if self.time_bnds is not None: time_bnds_var = netcdf.createVariable("time_bnds", float64, ("time", "time_nv",), zlib=self.zip_lvl, complevel=self.zip_lvl) if self.size > 1: time_bnds_var.set_collective(True) time_bnds_var[:] = date2num(self.get_full_time_bnds(), time_var.units, calendar="standard") # STATIONS stations = netcdf.createVariable("station", float64, ("station",), zlib=self.zip_lvl > 0, complevel=self.zip_lvl) stations.units = "" stations.axis = "X" stations.long_name = "" stations.standard_name = "station" if self.size > 1: stations.set_collective(True) stations[:] = self._station["data"] # LATITUDES lat = netcdf.createVariable("latitude", float64, self._lat_dim, zlib=self.zip_lvl > 0, complevel=self.zip_lvl) lat.units = "degrees_north" lat.axis = "Y" lat.long_name = "latitude coordinate" lat.standard_name = "latitude" if self.lat_bnds is not None: lat.bounds = "lat_bnds" if self.size > 1: lat.set_collective(True) lat[:] = self.get_full_latitudes()["data"] # LONGITUDES lon = netcdf.createVariable("longitude", float64, self._lon_dim, zlib=self.zip_lvl > 0, complevel=self.zip_lvl) lon.units = "degrees_east" lon.axis = "X" lon.long_name = "longitude coordinate" lon.standard_name = "longitude" if self.lon_bnds is not None: lon.bounds = "lon_bnds" if self.size > 1: lon.set_collective(True) lon[:] = self.get_full_longitudes()["data"]
[docs] def erase_flags(self): first_time_idx = self._get_time_id(self.hours_start, first=True) last_time_idx = self._get_time_id(self.hours_end, first=False) t_len = last_time_idx - first_time_idx self._qa["data"] = empty((len(self.get_full_longitudes()["data"]), t_len, 0)) self._flag["data"] = empty((len(self.get_full_longitudes()["data"]), t_len, 0)) return None
# noinspection DuplicatedCode def _get_coordinate_values(self, coordinate_info, coordinate_axis, bounds=False): """ Get the coordinate data of the current portion. Parameters ---------- coordinate_info : dict, list Dictionary with the "data" key with the coordinate variable values. and the attributes as other keys. coordinate_axis : str Name of the coordinate to extract. Accepted values: ["X"]. bounds : bool Boolean variable to know if there are coordinate bounds. Returns ------- values : dict Dictionary with the portion of data corresponding to the rank. """ if coordinate_info is None: return None if not isinstance(coordinate_info, dict): values = {"data": deepcopy(coordinate_info)} else: values = deepcopy(coordinate_info) coordinate_len = len(values["data"].shape) if bounds: coordinate_len -= 1 if coordinate_axis == "X": if coordinate_len == 1: values["data"] = values["data"][self.read_axis_limits["x_min"]:self.read_axis_limits["x_max"]] elif coordinate_len == 2: values["data"] = values["data"][self.read_axis_limits["x_min"]:self.read_axis_limits["x_max"], self.read_axis_limits["t_min"]:self.read_axis_limits["t_max"]] elif coordinate_len == 3: values["data"] = values["data"][self.read_axis_limits["x_min"]:self.read_axis_limits["x_max"], self.read_axis_limits["t_min"]:self.read_axis_limits["t_max"], :] else: raise NotImplementedError("The coordinate has wrong dimensions: {dim}".format( dim=values["data"].shape)) return values # noinspection DuplicatedCode def _read_variable(self, var_name): """ Read the corresponding variable data according to the current rank. Parameters ---------- var_name : str Name of the variable to read. Returns ------- data: array Portion of the variable data corresponding to the rank. """ nc_var = self.dataset.variables[var_name] var_dims = nc_var.dimensions # Read data in 1 or 2 dimensions if len(var_dims) < 2: data = nc_var[self.read_axis_limits["x_min"]:self.read_axis_limits["x_max"]] elif len(var_dims) == 2: data = nc_var[self.read_axis_limits["x_min"]:self.read_axis_limits["x_max"], self.read_axis_limits["t_min"]:self.read_axis_limits["t_max"]] elif len(var_dims) == 3: data = nc_var[self.read_axis_limits["x_min"]:self.read_axis_limits["x_max"], self.read_axis_limits["t_min"]:self.read_axis_limits["t_max"], :] else: raise NotImplementedError("Error with {0}. Only can be read netCDF with 3 dimensions or less".format( var_name)) # Unmask array data = self._unmask_array(data) return data # noinspection DuplicatedCode def _create_variables(self, netcdf, chunking=False): """ Create the netCDF file variables. Parameters ---------- netcdf : Dataset netcdf4-python open Dataset. chunking : bool Indicates if you want to chunk the output netCDF. """ if self.variables is not None: for i, (var_name, var_dict) in enumerate(self.variables.items()): # Get data type if "dtype" in var_dict.keys(): var_dtype = var_dict["dtype"] if (var_dict["data"] is not None) and (var_dtype != var_dict["data"].dtype): msg = "WARNING!!! " msg += "Different data types for variable {0}. ".format(var_name) msg += "Input dtype={0}. Data dtype={1}.".format(var_dtype, var_dict["data"].dtype) warn(msg) sys.stderr.flush() try: var_dict["data"] = var_dict["data"].astype(var_dtype) except Exception: raise TypeError("It was not possible to cast the data to the input dtype.") else: var_dtype = var_dict["data"].dtype if var_dtype is object: raise TypeError("Data dtype is object. Define dtype explicitly as dictionary key 'dtype'") # Get dimensions when reading datasets if "dimensions" in var_dict.keys(): var_dims = var_dict["dimensions"] # Get dimensions when creating new datasets else: if len(var_dict["data"].shape) == 1: # For data that depends only on station (e.g. station_code) var_dims = self._var_dim else: # For data that is dependent on time and station (e.g. PM10) var_dims = self._var_dim + ("time",) if var_dict["data"] is not None: # Ensure data is of type numpy array (to create NES) if not isinstance(var_dict["data"], (ndarray, generic)): try: var_dict["data"] = array(var_dict["data"]) except AttributeError: raise AttributeError("Data for variable {0} must be a numpy array.".format(var_name)) # Convert list of strings to chars for parallelization if issubdtype(var_dtype, character): var_dict["data_aux"] = self._str2char(var_dict["data"]) var_dims += ("strlen",) var_dtype = "S1" if self.info: print("Rank {0:03d}: Writing {1} var ({2}/{3})".format(self.rank, var_name, i + 1, len(self.variables))) if not chunking: var = netcdf.createVariable(var_name, var_dtype, var_dims, zlib=self.zip_lvl > 0, complevel=self.zip_lvl) else: if self.master: chunk_size = var_dict["data"].shape else: chunk_size = None chunk_size = self.comm.bcast(chunk_size, root=0) var = netcdf.createVariable(var_name, var_dtype, var_dims, zlib=self.zip_lvl > 0, complevel=self.zip_lvl, chunksizes=chunk_size) if self.info: print("Rank {0:03d}: Var {1} created ({2}/{3})".format( self.rank, var_name, i + 1, len(self.variables))) if self.size > 1: var.set_collective(True) if self.info: print("Rank {0:03d}: Var {1} collective ({2}/{3})".format( self.rank, var_name, i + 1, len(self.variables))) for att_name, att_value in var_dict.items(): if att_name == "data": if self.info: print("Rank {0:03d}: Filling {1})".format(self.rank, var_name)) if "data_aux" in var_dict.keys(): att_value = var_dict["data_aux"] if len(att_value.shape) == 1: try: var[self.write_axis_limits["x_min"]:self.write_axis_limits["x_max"]] = att_value except IndexError: raise IndexError("Different shapes. out_shape={0}, data_shp={1}".format( var[self.write_axis_limits["x_min"]:self.write_axis_limits["x_max"]].shape, att_value.shape)) except ValueError: raise ValueError("Axis limits cannot be accessed. out_shape={0}, data_shp={1}".format( var[self.write_axis_limits["x_min"]:self.write_axis_limits["x_max"]].shape, att_value.shape)) elif len(att_value.shape) == 2: if "strlen" in var_dims: try: var[self.write_axis_limits["x_min"]:self.write_axis_limits["x_max"], :] = att_value except IndexError: raise IndexError("Different shapes. out_shape={0}, data_shp={1}".format( var[self.write_axis_limits["x_min"]:self.write_axis_limits["x_max"], :].shape, att_value.shape)) except ValueError: raise ValueError("Axis limits cannot be accessed. out_shape={0}, data_shp={1}".format( var[self.write_axis_limits["x_min"]:self.write_axis_limits["x_max"], :].shape, att_value.shape)) else: try: var[self.write_axis_limits["x_min"]:self.write_axis_limits["x_max"], self.write_axis_limits["t_min"]:self.write_axis_limits["t_max"]] = att_value except IndexError: raise IndexError("Different shapes. out_shape={0}, data_shp={1}".format( var[self.write_axis_limits["x_min"]:self.write_axis_limits["x_max"], self.write_axis_limits["t_min"]:self.write_axis_limits["t_max"]].shape, att_value.shape)) except ValueError: out_shape = var[self.write_axis_limits["x_min"]:self.write_axis_limits["x_max"], self.write_axis_limits["t_min"]:self.write_axis_limits["t_max"]].shape raise ValueError("Axis limits cannot be accessed. out_shape={0}, data_shp={1}".format( out_shape, att_value.shape)) elif len(att_value.shape) == 3: try: var[self.write_axis_limits["x_min"]:self.write_axis_limits["x_max"], self.write_axis_limits["t_min"]:self.write_axis_limits["t_max"], :] = att_value except IndexError: raise IndexError("Different shapes. out_shape={0}, data_shp={1}".format( var[self.write_axis_limits["x_min"]:self.write_axis_limits["x_max"], self.write_axis_limits["t_min"]:self.write_axis_limits["t_max"], :].shape, att_value.shape)) except ValueError: raise ValueError("Axis limits cannot be accessed. out_shape={0}, data_shp={1}".format( var[self.write_axis_limits["x_min"]:self.write_axis_limits["x_max"], self.write_axis_limits["t_min"]:self.write_axis_limits["t_max"], :].shape, att_value.shape)) if self.info: print("Rank {0:03d}: Var {1} data ({2}/{3})".format(self.rank, var_name, i + 1, len(self.variables))) elif att_name not in ["chunk_size", "var_dims", "dimensions", "dtype", "data_aux"]: var.setncattr(att_name, att_value) if "data_aux" in var_dict.keys(): del var_dict["data_aux"] self._set_var_crs(var) if self.info: print("Rank {0:03d}: Var {1} completed ({2}/{3})".format(self.rank, var_name, i + 1, len(self.variables))) return None # noinspection DuplicatedCode def _gather_data(self, data_to_gather): """ Gather all the variable data into the MPI rank 0 to perform a serial write. Returns ------- data_to_gather: dict Variables to gather. """ data_list = deepcopy(data_to_gather) for var_name, var_info in data_list.items(): try: # noinspection PyArgumentList data_aux = self.comm.gather(data_list[var_name]["data"], root=0) if self.rank == 0: shp_len = len(data_list[var_name]["data"].shape) # concatenate over station if self.parallel_method == "X": if shp_len == 1: # dimensions = (station) axis = 0 elif shp_len == 2: # dimensions = (station, strlen) or # dimensions = (station, time) axis = 0 else: msg = "The points NetCDF must have " msg += "surface values (without levels)." raise NotImplementedError(msg) elif self.parallel_method == "T": # concatenate over time if shp_len == 1: # dimensions = (station) axis = None elif shp_len == 2: if "strlen" in var_info["dimensions"]: # dimensions = (station, strlen) axis = None else: # dimensions = (station, time) axis = 1 else: msg = "The points NetCDF must have " msg += "surface values (without levels)." raise NotImplementedError(msg) else: raise NotImplementedError( "Parallel method '{meth}' is not implemented. Use one of these: {accept}".format( meth=self.parallel_method, accept=["X", "T"])) data_list[var_name]["data"] = concatenate(data_aux, axis=axis) except Exception as e: msg = f"**ERROR** an error has occurred while gathering the '{var_name}' variable.\n" print(msg) sys.stderr.write(msg) print(e) sys.stderr.write(str(e)) sys.stderr.flush() self.comm.Abort(1) return data_list def _create_metadata(self, netcdf): """ Create metadata variables. Parameters ---------- netcdf : Dataset NetCDF object. """ # N FLAG CODES flag = netcdf.createVariable("flag", int64, ("station", "time", "N_flag_codes",), zlib=self.zip_lvl > 0, complevel=self.zip_lvl) flag.units = "" flag.axis = "" flag.long_name = "" flag.standard_name = "flag" if self.size > 1: flag.set_collective(True) flag[:] = self._flag["data"] # N QA CODES qa = netcdf.createVariable("qa", int64, ("station", "time", "N_qa_codes",), zlib=self.zip_lvl > 0, complevel=self.zip_lvl) qa.units = "" qa.axis = "" qa.long_name = "" qa.standard_name = "N_qa_codes" if self.size > 1: qa.set_collective(True) qa[:] = self._qa["data"] return None
[docs] def to_netcdf(self, path, compression_level=0, serial=False, info=False, chunking=False, nc_type="NES", keep_open=False): """ Write the netCDF output file. Parameters ---------- keep_open : bool nc_type : str path : str Path to the output netCDF file. compression_level : int Level of compression (0 to 9) Default: 0 (no compression). serial : bool Indicates if you want to write in serial or not. Default: False. info : bool Indicates if you want to print the information of each writing step by stdout Default: False. chunking : bool Indicates if you want a chunked netCDF output. Only available with non-serial writes. Default: False. """ if (not serial) and (self.size > 1): msg = "WARNING!!! " msg += "GHOST datasets cannot be written in parallel yet. " msg += "Changing to serial mode." warn(msg) sys.stderr.flush() super(PointsNesGHOST, self).to_netcdf(path, compression_level=compression_level, serial=True, info=info, chunking=chunking) return None
[docs] def to_points(self): """ Transform a PointsNesGHOST into a PointsNes object Returns ---------- points_nes : nes.Nes Points Nes Object (without GHOST metadata variables) """ points_nes = PointsNes(comm=self.comm, info=self.info, balanced=self.balanced, parallel_method=self.parallel_method, avoid_first_hours=self.hours_start, avoid_last_hours=self.hours_end, first_level=self.first_level, last_level=self.last_level, create_nes=True, lat=self.lat["data"], lon=self.lon["data"], times=self.time ) # The version attribute in GHOST files prior to 1.3.3 is called data_version, after it is version if "version" in self.global_attrs: ghost_version = self.global_attrs["version"] elif "data_version" in self.global_attrs: ghost_version = self.global_attrs["data_version"] else: ghost_version = "0.0.0" metadata_variables = self.get_standard_metadata(ghost_version) self.free_vars(metadata_variables) self.free_vars("station") points_nes.variables = deepcopy(self.variables) return points_nes
[docs] @staticmethod def get_standard_metadata(ghost_version): """ Get all possible GHOST variables for each version. Parameters ---------- ghost_version : str Version of GHOST file. Returns ---------- metadata_variables[GHOST_version] : list A List of metadata variables for a certain GHOST version """ # This metadata variables are metadata_variables = {"1.4": ["GHOST_version", "station_reference", "station_timezone", "latitude", "longitude", "altitude", "sampling_height", "measurement_altitude", "ellipsoid", "horizontal_datum", "vertical_datum", "projection", "distance_to_building", "distance_to_kerb", "distance_to_junction", "distance_to_source", "street_width", "street_type", "daytime_traffic_speed", "daily_passing_vehicles", "data_level", "climatology", "station_name", "city", "country", "administrative_country_division_1", "administrative_country_division_2", "population", "representative_radius", "network", "associated_networks", "area_classification", "station_classification", "main_emission_source", "land_use", "terrain", "measurement_scale", "ESDAC_Iwahashi_landform_classification", "ESDAC_modal_Iwahashi_landform_classification_5km", "ESDAC_modal_Iwahashi_landform_classification_25km", "ESDAC_Meybeck_landform_classification", "ESDAC_modal_Meybeck_landform_classification_5km", "ESDAC_modal_Meybeck_landform_classification_25km", "GHSL_settlement_model_classification", "GHSL_modal_settlement_model_classification_5km", "GHSL_modal_settlement_model_classification_25km", "Joly-Peuch_classification_code", "Koppen-Geiger_classification", "Koppen-Geiger_modal_classification_5km", "Koppen-Geiger_modal_classification_25km", "MODIS_MCD12C1_v6_IGBP_land_use", "MODIS_MCD12C1_v6_modal_IGBP_land_use_5km", "MODIS_MCD12C1_v6_modal_IGBP_land_use_25km", "MODIS_MCD12C1_v6_UMD_land_use", "MODIS_MCD12C1_v6_modal_UMD_land_use_5km", "MODIS_MCD12C1_v6_modal_UMD_land_use_25km", "MODIS_MCD12C1_v6_LAI", "MODIS_MCD12C1_v6_modal_LAI_5km", "MODIS_MCD12C1_v6_modal_LAI_25km", "WMO_region", "WWF_TEOW_terrestrial_ecoregion", "WWF_TEOW_biogeographical_realm", "WWF_TEOW_biome", "UMBC_anthrome_classification", "UMBC_modal_anthrome_classification_5km", "UMBC_modal_anthrome_classification_25km", "EDGAR_v4.3.2_annual_average_BC_emissions", "EDGAR_v4.3.2_annual_average_CO_emissions", "EDGAR_v4.3.2_annual_average_NH3_emissions", "EDGAR_v4.3.2_annual_average_NMVOC_emissions", "EDGAR_v4.3.2_annual_average_NOx_emissions", "EDGAR_v4.3.2_annual_average_OC_emissions", "EDGAR_v4.3.2_annual_average_PM10_emissions", "EDGAR_v4.3.2_annual_average_biogenic_PM2.5_emissions", "EDGAR_v4.3.2_annual_average_fossilfuel_PM2.5_emissions", "EDGAR_v4.3.2_annual_average_SO2_emissions", "ASTER_v3_altitude", "ETOPO1_altitude", "ETOPO1_max_altitude_difference_5km", "GHSL_built_up_area_density", "GHSL_average_built_up_area_density_5km", "GHSL_average_built_up_area_density_25km", "GHSL_max_built_up_area_density_5km", "GHSL_max_built_up_area_density_25km", "GHSL_population_density", "GHSL_average_population_density_5km", "GHSL_average_population_density_25km", "GHSL_max_population_density_5km", "GHSL_max_population_density_25km", "GPW_population_density", "GPW_average_population_density_5km", "GPW_average_population_density_25km", "GPW_max_population_density_5km", "GPW_max_population_density_25km", "NOAA-DMSP-OLS_v4_nighttime_stable_lights", "NOAA-DMSP-OLS_v4_average_nighttime_stable_lights_5km", "NOAA-DMSP-OLS_v4_average_nighttime_stable_lights_25km", "NOAA-DMSP-OLS_v4_max_nighttime_stable_lights_5km", "NOAA-DMSP-OLS_v4_max_nighttime_stable_lights_25km", "OMI_level3_column_annual_average_NO2", "OMI_level3_column_cloud_screened_annual_average_NO2", "OMI_level3_tropospheric_column_annual_average_NO2", "OMI_level3_tropospheric_column_cloud_screened_annual_average_NO2", "GSFC_coastline_proximity", "primary_sampling_type", "primary_sampling_instrument_name", "primary_sampling_instrument_documented_flow_rate", "primary_sampling_instrument_reported_flow_rate", "primary_sampling_process_details", "primary_sampling_instrument_manual_name", "primary_sampling_further_details", "sample_preparation_types", "sample_preparation_techniques", "sample_preparation_process_details", "sample_preparation_further_details", "measurement_methodology", "measuring_instrument_name", "measuring_instrument_sampling_type", "measuring_instrument_documented_flow_rate", "measuring_instrument_reported_flow_rate", "measuring_instrument_process_details", "measuring_instrument_process_details", "measuring_instrument_manual_name", "measuring_instrument_further_details", "measuring_instrument_reported_units", "measuring_instrument_reported_lower_limit_of_detection", "measuring_instrument_documented_lower_limit_of_detection", "measuring_instrument_reported_upper_limit_of_detection", "measuring_instrument_documented_upper_limit_of_detection", "measuring_instrument_reported_uncertainty", "measuring_instrument_documented_uncertainty", "measuring_instrument_reported_accuracy", "measuring_instrument_documented_accuracy", "measuring_instrument_reported_precision", "measuring_instrument_documented_precision", "measuring_instrument_reported_zero_drift", "measuring_instrument_documented_zero_drift", "measuring_instrument_reported_span_drift", "measuring_instrument_documented_span_drift", "measuring_instrument_reported_zonal_drift", "measuring_instrument_documented_zonal_drift", "measuring_instrument_reported_measurement_resolution", "measuring_instrument_documented_measurement_resolution", "measuring_instrument_reported_absorption_cross_section", "measuring_instrument_documented_absorption_cross_section", "measuring_instrument_inlet_information", "measuring_instrument_calibration_scale", "network_provided_volume_standard_temperature", "network_provided_volume_standard_pressure", "retrieval_algorithm", "principal_investigator_name", "principal_investigator_institution", "principal_investigator_email_address", "contact_name", "contact_institution", "contact_email_address", "meta_update_stamp", "data_download_stamp", "data_revision_stamp", "network_sampling_details", "network_uncertainty_details", "network_maintenance_details", "network_qa_details", "network_miscellaneous_details", "data_licence", "process_warnings", "temporal_resolution", "reported_lower_limit_of_detection_per_measurement", "reported_upper_limit_of_detection_per_measurement", "reported_uncertainty_per_measurement", "derived_uncertainty_per_measurement", "day_night_code", "weekday_weekend_code", "season_code", "hourly_native_representativity_percent", "hourly_native_max_gap_percent", "daily_native_representativity_percent", "daily_representativity_percent", "daily_native_max_gap_percent", "daily_max_gap_percent", "monthly_native_representativity_percent", "monthly_representativity_percent", "monthly_native_max_gap_percent", "monthly_max_gap_percent", "annual_native_representativity_percent", "annual_native_max_gap_percent", "all_representativity_percent", "all_max_gap_percent"], } return metadata_variables[ghost_version]
# noinspection DuplicatedCode
[docs] def add_variables_to_shapefile(self, var_list, idx_lev=0, idx_time=0): """ Add variables data to shapefile. var_list : list, str List (or single string) of the variables to be loaded and saved in the shapefile. idx_lev : int Index of vertical level for which the data will be saved in the shapefile. idx_time : int Index of time for which the data will be saved in the shapefile. """ if idx_lev != 0: msg = "Error: Points dataset has no level (Level: {0}).".format(idx_lev) raise ValueError(msg) for var_name in var_list: # station as dimension if len(self.variables[var_name]["dimensions"]) == 1: self.shapefile[var_name] = self.variables[var_name]["data"][:].ravel() # station and time as dimensions else: self.shapefile[var_name] = self.variables[var_name]["data"][:, idx_time].ravel() return None
@staticmethod def _get_axis_index_(axis): if axis == "T": value = 1 elif axis == "X": value = 0 else: raise ValueError("Unknown axis: {0}".format(axis)) return value @staticmethod def _set_var_crs(var): """ Set the grid_mapping Parameters ---------- var : Variable netCDF4-python variable object. """ return None