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
Beispiel #3
0
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
Beispiel #6
0
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
Beispiel #7
0
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