def retrieve_model_point(data_code: str, parameter: str, start_time: pd.Timestamp, forecast_time: Union[str, pd.Timedelta, Tuple], level_type: Union[str, int], level: Union[int, float], point: Union[Tuple[float, float], List[Tuple[float, float]]] = None, station: Union[List[str], str] = None, config_file: Optional[str] = None) -> pd.DataFrame: interface_config = { "name": "getNafpEle", "point": None, "time": "Time", "level": "Level", "valid_time": "Validtime", "station": None, } params = { "dataCode": data_code, "fcstEle": parameter, "levelType": str(level_type), "fcstLevel": str(level) } time = _get_time_string(start_time) params["time"] = time def _get_valid_time(f): if isinstance(f, str): f = pd.to_timedelta(f) return int(f / pd.Timedelta(hours=1)) if isinstance(forecast_time, str or pd.Timedelta): valid_time = _get_valid_time(forecast_time) params["validTime"] = str(valid_time) interface_config["valid_time"] = "Validtime" elif isinstance(forecast_time, Tuple): interface_config["valid_time"] = "ValidtimeRange" params["minVT"] = str(_get_valid_time(forecast_time[0])) params["maxVT"] = str(_get_valid_time(forecast_time[1])) if point is not None: _get_point_params(point, params, interface_config) if station is not None: _get_station_params(station, params, interface_config) interface_id = _get_interface_id(interface_config) logger.info(f"interface_id: {interface_id}") client = _get_client(config_file) result = client.callAPI_to_array2D(interface_id, params) if result.request.error_code != 0: logger.warning( f"request error {result.request.error_code}: {result.request.error_message}" ) df = result.to_pandas() return df
def _do_request( self, interface_id: str, method: str, params: Dict, server_id: str, success_handler: Callable[[bytes], Any], failure_handler: Callable[[bytes], Any], exception_handler: Callable[[Exception], Any], ): fetch_url = self._get_fetch_url( interface_id, method, params, server_id ) logger.info(f"fetch url: {fetch_url}") result = self._connection.make_request( fetch_url, success_handler, failure_handler, exception_handler ) return result
def download_obs_file( data_code: str, elements: str = None, time: typing.Union[pd.Interval, pd.Timestamp, typing.List, pd.Timedelta] = None, station: typing.Union[str, typing.List, typing.Tuple] = None, region=None, station_level: typing.Union[str, typing.List[str]] = None, order: str = None, count: int = None, output_dir: str = "./", interface_data_type="Surf", config_file: typing.Union[str, Path] = None, **kwargs, ): """ 下载地面观测数据文件 默认对应 CMADaaS 中以 `getSurfFile` 开头的一系列数据接口 **区域筛选条件** - 经纬度范围 .. code-block:: python { "type": "rect", "start_longitude": 115.7, "end_longitude": 117.4, "start_latitude": 41.6, "end_latitude": 39.4, } - 流域 .. code-block:: python { "type": "basin", "basin_codes": "CJLY" } - 地区 .. code-block:: python { "type": "region", "admin_codes": "110000" } Parameters ---------- data_code: 数据种类,即 CMADaaS 中的资料代码 elements: 要素字段代码,以逗号分隔 time: 时间筛选条件,支持单个时间,时间列表,时间段和时间间隔 - 时间对象:``pd.Timestamp`` 类型,单个时间点,对应接口的 times 参数 - 时间列表:``typing.List[pd.Timestamp]`` 类型,多个时间列表,对应接口的 times 参数 - 时间段:``pd.Interval`` 类型,起止时间,定义区间端点是否闭合,对应接口的 timeRange 参数 - 时间间隔:``pd.Timedelta`` 类型,用于获取地面资料最新时次 (getSurfLatestTime),忽略其余筛选条件 station: 站点筛选条件,支持字符串,列表和元组 - 字符串:单个站点 - 列表:多个站点 - 元组:站点范围,二元组,第一个元素是起止站号 (minStaId),第二个元素是终止站号 (maxStaId) region: 区域筛选条件: - 经纬度范围 (rect) - 流域 (basin) - 地区 (region) station_level: 台站级别: - 011: 国家基准气候站 - 012: 基本气象站 - 013: 一般气象站 order: 排序字段 count: 最大返回记录数,对应接口的 limitCnt 参数 output_dir: 保存文件的目录 interface_data_type: 资料类型 config_file: 配置文件路径 kwargs: 其他需要传递给 MUSIC 接口的参数,例如: - eleValueRanges: 要素值范围 - hourSeparate: 小时取整条件 - minSeparate: 分钟取整条件 Returns ------- """ # if elements is None: # elements = STATION_DATASETS[data_code]["elements"] interface_config = { "name": f"get{interface_data_type}File", "region": None, "time": None, "station": None, } params = { "dataCode": data_code, } if order is not None: params["orderby"] = order if elements is not None: params["elements"] = elements if count is not None: params["limitCnt"] = count if isinstance(time, pd.Interval): interface_config["time"] = "TimeRange" params["timeRange"] = _get_time_range_string(time) elif isinstance(time, pd.Timestamp): interface_config["time"] = "Time" params["times"] = _get_time_string(time) elif isinstance(time, typing.List): interface_config["time"] = "Time" params["times"] = ",".join([_get_time_string(t) for t in time]) elif isinstance(time, pd.Timedelta): interface_config["name"] = "getSurfLatestTime" params["latestTime"] = str(int(time / pd.to_timedelta("1h"))) del params["orderby"] del params["elements"] if isinstance(station, str or int): interface_config["station"] = "StaID" params["staIds"] = station elif isinstance(station, typing.List): interface_config["station"] = "StaID" params["staIds"] = ",".join(station) elif isinstance(station, typing.Tuple): interface_config["station"] = "StaIdRange" params["minStaId"] = station[0] params["maxStaId"] = station[1] if region is not None: _get_region_params(region, params, interface_config) if station_level is not None: del params["orderby"] if isinstance(station_level, str): params["staLevels"] = station_level if interface_config["station"] is None: interface_config["station"] = "StaLevels" elif isinstance(station_level, typing.List): params["staLevels"] = ",".join(station_level) if interface_config["station"] is None: interface_config["station"] = "StaLevels" params.update(**kwargs) interface_id = _get_interface_id(interface_config) logger.info(f"interface_id: {interface_id}") client = _get_client(config_file) result = client.callAPI_to_downFile(interface_id, params, file_dir=output_dir) if result.request.error_code != 0: logger.warning( f"request error {result.request.error_code}: {result.request.error_message}" ) files_info = result.files_info file_list = [] for f in files_info: file_list.append(Path(output_dir, f.file_name)) return file_list
def retrieve_obs_station( data_code: str = "SURF_CHN_MUL_HOR", elements: str = None, time: typing.Union[pd.Interval, pd.Timestamp, typing.List, pd.Timedelta] = None, station: typing.Union[str, typing.List, typing.Tuple] = None, region=None, station_level: typing.Union[str, typing.List[str]] = None, order: str = "Station_ID_d:asc", count: int = None, config_file: typing.Union[str, Path] = None, **kwargs, ) -> pd.DataFrame: """ 检索地面站点观测数据资料。 对应 CMADaaS 中以 `getSurfEle` 开头的一系列数据接口 **区域筛选条件** - 经纬度范围 .. code-block:: python { "type": "rect", "start_longitude": 115.7, "end_longitude": 117.4, "start_latitude": 41.6, "end_latitude": 39.4, } - 流域 .. code-block:: python { "type": "basin", "basin_codes": "CJLY" } - 地区 .. code-block:: python { "type": "region", "admin_codes": "110000" } Parameters ---------- data_code: 数据种类,即 CMADaaS 中的资料代码 elements: 要素字段代码,以逗号分隔 time: 时间筛选条件,支持单个时间,时间列表,时间段和时间间隔 - 时间对象:``pd.Timestamp`` 类型,单个时间点,对应接口的 times 参数 - 时间列表:``typing.List[pd.Timestamp]`` 类型,多个时间列表,对应接口的 times 参数 - 时间段:``pd.Interval`` 类型,起止时间,定义区间端点是否闭合,对应接口的 timeRange 参数 - 时间间隔:``pd.Timedelta`` 类型,用于获取地面资料最新时次 (getSurfLatestTime),忽略其余筛选条件 station: 站点筛选条件,支持字符串,列表和元组 - 字符串:单个站点 - 列表:多个站点 - 元组:站点范围,二元组,第一个元素是起止站号 (minStaId),第二个元素是终止站号 (maxStaId) region: 区域筛选条件: - 经纬度范围 (rect) - 流域 (basin) - 地区 (region) station_level: 台站级别: - 011: 国家基准气候站 - 012: 基本气象站 - 013: 一般气象站 order: 排序字段 count: 最大返回记录数,对应接口的 limitCnt 参数 config_file: 配置文件路径 kwargs: 其他需要传递给 MUSIC 接口的参数,例如: - eleValueRanges: 要素值范围 - hourSeparate: 小时取整条件 - minSeparate: 分钟取整条件 Returns ------- pd.DataFrame 站点观测资料表格数据,列名为 elements 中的值 """ station_dataset_config = load_dataset_config("station") if elements is None: elements = station_dataset_config[data_code]["elements"] interface_config = { "name": "getSurfEle", "region": None, "time": None, "station": None, } params = { "dataCode": data_code, "elements": elements, "orderby": order, } if count is not None: params["limitCnt"] = count if isinstance(time, pd.Interval): interface_config["time"] = "TimeRange" params["timeRange"] = _get_time_range_string(time) elif isinstance(time, pd.Timestamp): interface_config["time"] = "Time" params["times"] = _get_time_string(time) elif isinstance(time, typing.List): interface_config["time"] = "Time" params["times"] = ",".join([_get_time_string(t) for t in time]) elif isinstance(time, pd.Timedelta): interface_config["name"] = "getSurfLatestTime" params["latestTime"] = str(int(time / pd.to_timedelta("1h"))) del params["orderby"] del params["elements"] if isinstance(station, str or int): interface_config["station"] = "StaID" params["staIds"] = station elif isinstance(station, typing.List): interface_config["station"] = "StaID" params["staIds"] = ",".join(station) elif isinstance(station, typing.Tuple): interface_config["station"] = "StaIdRange" params["minStaId"] = station[0] params["maxStaId"] = station[1] if region is not None: _get_region_params(region, params, interface_config) if station_level is not None: del params["orderby"] if isinstance(station_level, str): params["staLevels"] = station_level if interface_config["station"] is None: interface_config["station"] = "StaLevels" elif isinstance(station_level, typing.List): params["staLevels"] = ",".join(station_level) if interface_config["station"] is None: interface_config["station"] = "StaLevels" params.update(**kwargs) interface_id = _get_interface_id(interface_config) logger.info(f"interface_id: {interface_id}") client = _get_client(config_file) result = client.callAPI_to_array2D(interface_id, params) if result.request.error_code != 0: logger.warning(f"request error {result.request.error_code}: {result.request.error_message}") df = result.to_pandas() return df
def retrieve_obs_upper_air( data_code: str = "UPAR_GLB_MUL_FTM", elements: str = None, time: typing.Union[pd.Interval, pd.Timestamp, typing.List, pd.Timedelta] = None, level_type: typing.Union[str, typing.Tuple[str]] = None, level: typing.Union[float, int, typing.List[typing.Union[float, int]], typing.Tuple] = None, station: typing.Union[str, int, typing.List, typing.Tuple] = None, region=None, station_level: typing.Union[str, typing.List[str]] = None, order: str = None, count: int = None, interface_data_type: str = None, config_file: typing.Union[str, Path] = None, **kwargs, ) -> pd.DataFrame: """ 检索高空观测数据资料。 对应 CMADaaS 中以 `getUparEle` 开头的一系列数据接口 **区域筛选条件** - 经纬度范围 .. code-block:: python { "type": "rect", "start_longitude": 115.7, "end_longitude": 117.4, "start_latitude": 41.6, "end_latitude": 39.4, } - 流域 .. code-block:: python { "type": "basin", "basin_codes": "CJLY" } - 地区 .. code-block:: python { "type": "region", "admin_codes": "110000" } Parameters ---------- data_code: 数据种类,即 CMADaaS 中的资料代码 elements: 要素字段代码,以逗号分隔 time: 时间筛选条件,支持单个时间,时间列表,时间段和时间间隔 - 时间对象:``pd.Timestamp`` 类型,单个时间点,对应接口的 times 参数 - 时间列表:``typing.List[pd.Timestamp]`` 类型,多个时间列表,对应接口的 times 参数 - 时间段:``pd.Interval`` 类型,起止时间,定义区间端点是否闭合,对应接口的 timeRange 参数 - 时间间隔:``pd.Timedelta`` 类型,用于获取地面资料最新时次 (getSurfLatestTime),忽略其余筛选条件 level_type: 层次类型 - pl: 气压层 - gh/hgt: 位势高度 - vertical: 垂直探测仪一,例如 4096 表示湿度特征层 - fl/flight_level: 飞行高度 level: 层次 station: 站点筛选条件,支持字符串,列表和元组 - 字符串:单个站点 - 列表:多个站点 - 元组:站点范围,二元组,第一个元素是起止站号 (minStaId),第二个元素是终止站号 (maxStaId) region: 区域筛选条件: - 经纬度范围 (rect) - 流域 (basin) - 地区 (region) station_level: 台站级别: - 011: 国家基准气候站 - 012: 基本气象站 - 013: 一般气象站 order: 排序字段 count: 最大返回记录数,对应接口的 limitCnt 参数 interface_data_type: 资料类型,默认自动生成,或使用 _dataset.py 文件数据集配置的 interface_data_type 字段 config_file: 配置文件路径 kwargs: 其他需要传递给 MUSIC 接口的参数,例如: - eleValueRanges: 要素值范围 - hourSeparate: 小时取整条件 - minSeparate: 分钟取整条件 Returns ------- pd.DataFrame 高空观测资料表格数据,列名为 elements 中的值 """ if elements is None: elements = UPPER_AIR_DATASETS[data_code]["elements"] interface_config = { "name": "getUparEle", "region": None, "time": None, "station": None, "level": None, } if (interface_data_type is None and data_code in UPPER_AIR_DATASETS and "interface_data_type" in UPPER_AIR_DATASETS[data_code]): interface_data_type = UPPER_AIR_DATASETS[data_code][ "interface_data_type"] if interface_data_type is not None: interface_config["name"] = f"get{interface_data_type}Ele" params = { "dataCode": data_code, "elements": elements, } if order is not None: params["orderby"] = order if data_code in UPPER_AIR_DATASETS and "order_by" in UPPER_AIR_DATASETS[ data_code]: params["orderby"] = UPPER_AIR_DATASETS[data_code]["order_by"] if count is not None: params["limitCnt"] = count if isinstance(time, pd.Interval): interface_config["time"] = "TimeRange" params["timeRange"] = _get_time_range_string(time) elif isinstance(time, pd.Timestamp): interface_config["time"] = "Time" params["times"] = _get_time_string(time) elif isinstance(time, typing.List): interface_config["time"] = "Time" params["times"] = ",".join([_get_time_string(t) for t in time]) elif isinstance(time, pd.Timedelta): interface_config["name"] = "getSurfLatestTime" params["latestTime"] = str(int(time / pd.to_timedelta("1h"))) del params["orderby"] del params["elements"] _get_level_params(level=level, level_type=level_type, interface_config=interface_config, params=params) if isinstance(station, str) or isinstance(station, int): interface_config["station"] = "StaID" params["staIds"] = str(station) elif isinstance(station, typing.List): interface_config["station"] = "StaID" params["staIds"] = ",".join(station) elif isinstance(station, typing.Tuple): interface_config["station"] = "StaIdRange" params["minStaId"] = station[0] params["maxStaId"] = station[1] if region is not None: _get_region_params(region, params, interface_config) if station_level is not None: del params["orderby"] if isinstance(station_level, str): params["staLevels"] = station_level if interface_config["station"] is None: interface_config["station"] = "StaLevels" elif isinstance(station_level, typing.List): params["staLevels"] = ",".join(station_level) if interface_config["station"] is None: interface_config["station"] = "StaLevels" params.update(**kwargs) interface_id = _get_interface_id(interface_config) logger.info(f"interface_id: {interface_id}") params = _fix_params(interface_id, params) client = _get_client(config_file) result = client.callAPI_to_array2D(interface_id, params) if result.request.error_code != 0: logger.warning( f"request error {result.request.error_code}: {result.request.error_message}" ) df = result.to_pandas() return df
def download_model_file( data_code: str, parameter: Union[str, List[str]] = None, start_time: Union[pd.Interval, pd.Timestamp, List, pd.Timedelta] = None, forecast_time: Union[str, pd.Timedelta] = None, level_type: Union[str, int] = None, level: Union[int, float] = None, region: Dict = None, data_type: str = None, output_dir: Union[pathlib.Path, str] = None, config_file: Optional[str] = None ): interface_config = { "name": "getNafpFile", "element": None, "region": None, "time": None, "level": None, "valid_time": None } if output_dir is None: output_dir = "./" if data_type is None: data_type = "forecast" # data_type_mapper = { # "forecast": "getNafpEleGrid", # "analysis": "getNafpAnaEleGrid", # } # interface_config["name"] = data_type_mapper.get(data_type) params = { "dataCode": data_code, } if isinstance(parameter, str): params["fcstEle"] = parameter interface_config["element"] = "Element" elif isinstance(parameter, List): params["elements"] = ".".join(parameter) if level_type is not None: params["levelType"] = str(level_type) interface_config["level"] = "Level" if level is not None: params["fcstLevel"] = str(level) if isinstance(start_time, pd.Interval): interface_config["time"] = "TimeRange" params["timeRange"] = _get_time_range_string(start_time) elif isinstance(start_time, pd.Timestamp): interface_config["time"] = "Time" params["time"] = _get_time_string(start_time) elif isinstance(start_time, List): interface_config["time"] = "Time" params["times"] = ",".join([_get_time_string(t) for t in start_time]) elif isinstance(start_time, pd.Timedelta): interface_config["name"] = "getNafpLatestTime" params["latestTime"] = str(int(start_time / pd.to_timedelta("1h"))) # del params["orderby"] del params["elements"] if forecast_time is not None: interface_config["valid_time"] = "Validtime" if isinstance(forecast_time, str): forecast_time = pd.to_timedelta(forecast_time) valid_time = int(forecast_time / pd.Timedelta(hours=1)) params["validTime"] = str(valid_time) if region is not None: _get_region_params(region, params, interface_config) interface_id = _get_interface_id(interface_config) logger.info(f"interface_id: {interface_id}") client = _get_client(config_file) result = client.callAPI_to_downFile(interface_id, params, file_dir=output_dir) if result.request.error_code != 0: logger.warning(f"request error {result.request.error_code}: {result.request.error_message}") files_info = result.files_info for file_info in files_info: logger.info(file_info.file_name) return
def retrieve_model_grid(data_code: str, parameter: str, start_time: pd.Timestamp = None, forecast_time: Union[str, pd.Timedelta] = None, level_type: Union[str, int] = None, level: Union[int, float] = None, region: Dict = None, data_type: str = None, config_file: Optional[str] = None) -> xr.DataArray: interface_config = { "name": "getNafpEleGrid", "region": None, "time": None, "level": None, "valid_time": None } if data_type is None: data_type = "forecast" data_type_mapper = { "forecast": "getNafpEleGrid", "analysis": "getNafpAnaEleGrid", } interface_config["name"] = data_type_mapper.get(data_type) params = { "dataCode": data_code, "fcstEle": parameter, } if level_type is not None: params["levelType"] = str(level_type) interface_config["level"] = "Level" if level is not None: params["fcstLevel"] = str(level) if start_time is not None: interface_config["time"] = "Time" time = _get_time_string(start_time) params["time"] = time if forecast_time is not None: interface_config["valid_time"] = "Validtime" if isinstance(forecast_time, str): forecast_time = pd.to_timedelta(forecast_time) valid_time = int(forecast_time / pd.Timedelta(hours=1)) params["validTime"] = str(valid_time) if region is not None: _get_region_params(region, params, interface_config) interface_id = _get_interface_id(interface_config) logger.info(f"interface_id: {interface_id}") client = _get_client(config_file) result = client.callAPI_to_gridArray2D(interface_id, params) if result.request.error_code != 0: logger.warning( f"request error {result.request.error_code}: {result.request.error_message}" ) field = result.to_xarray() return field