def mock_download_era5sl_file(self, weather_factors, years, months, days,
                                  area_box, target_location):
        timeline = pd.date_range(end=datetime.utcnow(),
                                 periods=96,
                                 freq="1H",
                                 closed="left")
        coord_indices = coords_to_pd_index([
            GeoPosition(coordinate[0], coordinate[1])
            for coordinate in mock_coordinates
        ])
        coord = coord_indices[0]

        data_dict = {
            weather_factor: (
                ["time", "longitude", "latitude"],
                np.zeros(shape=(len(timeline), 1, 1), dtype=np.float64),
            )
            for weather_factor in weather_factors
        }

        ds = xr.Dataset(data_vars=data_dict,
                        coords={
                            "time": timeline,
                            "longitude": [coord[1]],
                            "latitude": [coord[0]]
                        })
        ds.to_netcdf(path=target_location, format="NETCDF4", engine="netcdf4")
def mock_single_value_dataset(mock_coordinates):
    mock_geoposition_coordinates = [
        GeoPosition(coordinate[0], coordinate[1])
        for coordinate in mock_coordinates
    ]
    mock_factor = ['temperature', 'precipitation', 'mock_unknown_field']
    timeline = [datetime.now()]
    coord_indices = coords_to_pd_index(mock_geoposition_coordinates)
    data_dict = {
        weather_factor: (
            ["time", "coord"],
            np.zeros(shape=(len(timeline), len(coord_indices)),
                     dtype=np.float64),
        )
        for weather_factor in mock_factor
    }
    ds = xr.Dataset(data_vars=data_dict,
                    coords={
                        "time": timeline,
                        "coord": coord_indices
                    })

    # Fill the single temperature value with 25 degrees Celsius
    ds['temperature'].data = [[np.float64(25), np.float64(25)]]

    # Fill the single precipitation value with 32 millimeters Celsius
    ds['precipitation'].data = [[np.float64(32), np.float64(32)]]

    # Fill the field to test the handling of unknown values with 66
    ds['mock_unknown_field'].data = [[np.float64(66), np.float64(66)]]
    return ds
def mock_dataset_era5(mock_coordinates, mock_factors):
    """
        returns a mock Xarray Dataset for
    Args:
        mock_coordinates:
        mock_factors:

    Returns:

    """
    timeline = pd.date_range(end=(datetime.utcnow() - relativedelta(days=6)),
                             periods=96,
                             freq="1H",
                             closed="left")
    coord_indices = coords_to_pd_index(
        [GeoPosition(51.873419, 5.705929),
         GeoPosition(53.2194, 6.5665)])
    weather_factors = mock_factors
    data_dict = {
        weather_factor: (
            ["time", "coord"],
            np.zeros(shape=(len(timeline), len(coord_indices)),
                     dtype=np.float64),
        )
        for weather_factor in weather_factors
    }
    ds = xr.Dataset(data_vars=data_dict,
                    coords={
                        "time": timeline,
                        "coord": coord_indices
                    })
    ds = ds.unstack("coord")
    return ds
    def get_weather(
        self,
        coords: List[GeoPosition],
        begin: datetime,
        end: datetime,
        weather_factors: List[str] = None,
    ) -> xr.Dataset:
        """
            The function that gathers and processes the requested Actuele Waarnemingen weather data from the KNMI site
            and returns it as an Xarray Dataset.
            (This model interprets directly from a HTML page, but the information is also available from the data
            platform. Due to it being rather impractically handled, we stick to the site for now.)
        Args:
            coords:             A list of GeoPositions containing the locations the data is requested for.
            begin:              A datetime containing the start of the period to request data for.
            end:                A datetime containing the end of the period to request data for.
            weather_factors:    A list of weather factors to request data for (in string format)
        Returns:
            An Xarray Dataset containing the weather data for the requested period, locations and factors.

        NOTES:
            As this model only return the current weather data the begin and end values are not actually used.
        """
        # TODO: Switch to KNMI Data Platform version when their naming has been fixed.

        updated_weather_factors = self._request_weather_factors(
            weather_factors)

        # Download the current weather data
        raw_ds = self._download_weather()

        # Get a list of the relevant STNs and choose the closest STN for each coordinate
        coords_stn, stns, coords_stn_ind = find_closest_stn_list(
            stations_actual, coords)

        # Select the data for the found closest STNs

        ds = raw_ds.sel(STN=coords_stn)

        data_dict = {
            var_name: (["time", "coord"], var.values)
            for var_name, var in ds.data_vars.items()
            if var_name in updated_weather_factors
            and var_name not in ["lat", "lon"]
        }

        timeline = ds.coords["time"].values

        ds = xr.Dataset(
            data_vars=data_dict,
            coords={
                "time": timeline,
                "coord": coords_to_pd_index(coords)
            },
        )
        ds = ds.unstack("coord")
        return ds
    def _prepare_weather_data(coordinates: List[GeoPosition], station_id, raw_ds):
        # A function that prepares the weather data for return by the API, by replacing the matching station with the
        # lat/lon location that was requested, and properly formatting the dimensions.

        # re-arrange stns
        ds = raw_ds.sel(station_code=station_id)

        # dict of data
        data_dict = {
            var_name: (["coord", "time"], var.values)
            for var_name, var in ds.data_vars.items()
        }
        timeline = ds.coords["date"].values

        ds = xr.Dataset(
            data_vars=data_dict,
            coords={"time": timeline, "coord": coords_to_pd_index(coordinates)},
        )
        ds = ds.unstack("coord")
        return ds
    def _download_weather(
        self,
        coordinates: List[GeoPosition],
        coords_stn_ind,
        stns,
        weather_factors: List[str],
    ):
        """
            A function that downloads the requested weather data, factor by factor.
        Args:
            coordinates:        A list of GeoPositions containing the coordinates to request data for.
            coords_stn_ind:     A list of station coordinates in order
            stns:               A list of stations by ID in the same order
            weather_factors:    A list of weather factors to request the data for (string based)
        Returns:
            An Xarray Dataset containing the requested factors for the requested period and location(s).
        """
        arr_dict = {}
        ds = xr.Dataset()
        for weather_factor in weather_factors:
            try:
                # Convert the factor to its request code
                code = self.to_si[weather_factor]["code"]
            except KeyError:
                # Requested factor is unknown: skip
                continue

            # Download the requested factor
            timeline, value = self._download_single_factor(stns, code)

            # add values
            arr_dict[weather_factor] = xr.DataArray(
                data=value[:, coords_stn_ind],
                dims=["time", "coord"],
                coords={"time": timeline, "coord": coords_to_pd_index(coordinates)},
                name=weather_factor,
            )
            ds = xr.merge(arr_dict.values(), join="outer")
        ds = ds.unstack("coord")
        return ds