Beispiel #1
0
 def __init__(self):
     """
         Give an access to IPM interface from agroservice
     """
     self.ipm = IPM()
     self.sources = None
     self.local_sources = []
Beispiel #2
0
 def __init__(self, name, forecast, endpoint, df=None):
     self.name = name
     self.forecast = forecast
     self.endpoint = endpoint
     self.sources = WeatherDataHub().__resources__
     self.ipm = IPM()
     self.df = df
Beispiel #3
0
class WeatherDataHub(object):
    """
        Allows to access at IPM weather resources 
        give the list of weather adapter (resources) available on IPM and allows access to weather data source
        
        ..doctest::
        >>> wsh = WeatherDataHub()
        >>> wsh.list_resources()
        >>> wsh.get_resource(name = 'Finnish Meteorological Institute measured data')

    """
    def __init__(self):
        """
            Give an access to IPM interface from agroservice
        """
        self.ipm = IPM()

    def list_resources(self):
        """
        get list of ressource available in IPM services

        Parameters:
        -----------

        Returns:
        ---------
            dictionnary with name and description of available weatherdatasource on IPM service
        """
        rep = self.ipm.get_weatherdatasource()
        return {item['name']: item['description'] for item in rep}

    def get_ressource(self, name):
        """
        Parameters:
        -----------
            name: name of weatherdatasource (available in list ressource)
            
        Returns:
        --------
            run weatherdatasource with the name of resource
        """
        rep = self.ipm.get_weatherdatasource()
        keys = [item['name'] for item in rep]
        if name in keys:
            return WeatherDataSource(name)
        else:
            raise NotImplementedError()
Beispiel #4
0
 def __init__(self, name):
     '''
     WeatherDataSource parameters to access at one weather data source of IPM 
     '''
     self.ipm = IPM()
     self.name = name
Beispiel #5
0
 def __init__(self):
     """
         Give an access to IPM interface from agroservice
     """
     self.ipm = IPM()
Beispiel #6
0
class WeatherDataSource(object):
    ''' 
    Allows to query weather data resource for a given date range and return
    meteorological data in the form of a Python data structure that keeps tracks
    of location and units.

    ..doctest::
        >>> ws = WeatherDataSource(name='Finnish Meteorological Institute measured data')
        >>> ws.station_ids()
        >>> ws.parameters()
        >>> ws.endpoint()
        >>> ws.check_forecast_endpoint()
        >>> ws.data(parameters=[1002,3002], station_id=101104, timeStart='2020-06-12',timeEnd='2020-07-03',timezone="UTC", altitude=70,longitude=14.3711,latitude=67.2828, ViewDataFrame=True)
    '''
    def __init__(self, name):
        '''
        WeatherDataSource parameters to access at one weather data source of IPM 
        '''
        self.ipm = IPM()
        self.name = name

    def station_ids(self):
        ''' 
        Get a dataframe with station id and coordinate

        Parameters:
        -----------

        Returns:
        --------
            a dataframe containing name, id and coordinate of station available for weather resource'''

        rep = self.ipm.get_weatherdatasource()

        values = {item['name']: item['spatial']['geoJSON'] for item in rep}

        station_ids = dict()
        coord = dict()

        for names in values:
            if 'features' in values[names]:
                station_ids[names] = [
                    values[names]['features'][item]['properties']
                    for item in range(len(values[names]['features']))
                ]
                coord[names] = [
                    values[names]['features'][item]['geometry']
                    for item in range(len(values[names]['features']))
                ]
            else:
                station_ids[names] = 'no stations for this ressources'
                coord[names] = 'no stations for this ressources'

        df_station_ids = pandas.DataFrame(station_ids[self.name])
        df_coord = pandas.DataFrame(coord[self.name])
        df = [df_station_ids, df_coord]
        data = pandas.concat(df, axis=1)
        data = data[["name", "id", "coordinates"]]
        return data

    def parameters(self):
        """
        Get list of available parameters for ressource

        Parameters:
        -----------

        Returns:
        --------
            a dictionnary containing common and optional parameters
        """
        rep = self.ipm.get_weatherdatasource()

        values = {item['name']: item['parameters'] for item in rep}

        if self.name in values:
            parameters = values[self.name]

        return parameters

    def endpoint(self):
        """
        Get endpoint associate at the name parameter of WeatherDataSource

        Parameters:
        -----------

        Returns:
        --------
            a endpoint (str) used in get_data function
        """
        endpoints = self.ipm.weatheradapter_service()

        if self.name in endpoints:
            endpoint = endpoints[self.name]

        return endpoint

    def check_forecast_endpoint(self):
        """
        Check if endpoint is a forecast or not
        
        Parameters:
        -----------

        Returns:
        --------
            Boolean value True if endpoint is a forecast endpoint either False
        """
        forcast_endpoints = self.ipm.weatheradapter_service(
            forecast=True).values()

        forcast = None

        if self.endpoint() in forcast_endpoints:
            forcast = True
        else:
            forcast = False

        return forcast

    def data(self,
             parameters=[1002, 3002],
             station_id=101104,
             timeStart='2020-06-12',
             timeEnd='2020-07-03',
             timezone="UTC",
             altitude=70,
             longitude=14.3711,
             latitude=67.2828,
             ViewDataFrame=True):
        """
        Get weather data from weatherdataressource

        Parameters:
        -----------
            parameters: list of parameters of weatherdata 
            station_id: (int) station id of weather station 
            daterange:  a pandas.date_range(start date, end date, freq='H', timezone(tz))
                        https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.date_range.html
            
            Only for forcast:
            ----------------
            altitude: (double) only for Met Norway Locationforecast WGS84 Decimal degrees
            latitude: (double) WGS84 Decimal degrees
            longitude: (double) WGS84 Decimal degrees
        
        Returns:
        --------
            return a dataframe (ViewDataFrame=True) or json format (ViewDataFrame=False) 
        """
        forcast = self.check_forecast_endpoint()

        if forcast == False:

            daterange = pandas.date_range(timeStart,
                                          timeEnd,
                                          freq='H',
                                          tz=timezone)

            timeStart = daterange[0].strftime('%Y-%m-%dT%H:%M:%S')
            timeEnd = daterange[-1].strftime('%Y-%m-%dT%H:%M:%S')
            if daterange.tz._tzname == 'UTC':
                timeStart += 'Z'
                timeEnd += 'Z'
            else:
                decstr = daterange[0].strftime('%z')
                decstr = decstr[:-2] + ':' + decstr[-2:]
                timeStart += decstr
                timeEnd += decstr

            interval = pandas.Timedelta(daterange.freq).seconds

            response = self.ipm.get_weatheradapter(endpoint=self.endpoint(),
                                                   credentials=None,
                                                   weatherStationId=station_id,
                                                   timeStart=timeStart,
                                                   timeEnd=timeEnd,
                                                   interval=interval,
                                                   parameters=parameters)

            if ViewDataFrame == True:
                data = {
                    str(var): vals
                    for var, vals in zip(
                        response['weatherParameters'],
                        zip(*response['locationWeatherData'][0]['data']))
                }
                df = pandas.DataFrame(data)
                df.index = daterange
                # TODO : get all what is needed for intantiating a WeatherData object (meta, units, ...) and retrun it
                return df
            else:
                return response

        if forcast == True:
            response = self.ipm.get_weatheradapter_forecast(
                endpoint=self.endpoint(),
                altitude=altitude,
                latitude=latitude,
                longitude=longitude)

            daterange = pandas.date_range(response['timeStart'],
                                          response['timeEnd'],
                                          freq='H',
                                          tz='UTC')

            timeStart = daterange[0].strftime('%Y-%m-%dT%H:%M:%S')
            timeEnd = daterange[-1].strftime('%Y-%m-%dT%H:%M:%S')
            if daterange.tz._tzname == 'UTC':
                timeStart += 'Z'
                timeEnd += 'Z'
            else:
                decstr = daterange[0].strftime('%z')
                decstr = decstr[:-2] + ':' + decstr[-2:]
                timeStart += decstr
                timeEnd += decstr

            interval = pandas.Timedelta(daterange.freq).seconds

            if ViewDataFrame == True:
                data = {
                    str(var): vals
                    for var, vals in zip(
                        response['weatherParameters'],
                        zip(*response['locationWeatherData'][0]['data']))
                }
                df = pandas.DataFrame(data)
                df.index = daterange
                # TODO : get all what is needed for intantiating a WeatherData object (meta, units, ...) and retrun it
                return df
            else:
                return response
Beispiel #7
0
import numpy as np
import xarray as xr
import pandas as pd
from metpy.units import units
import matplotlib.pyplot as plt

from agroservices import IPM

ipm = IPM()


def data(parameters=[1002, 3002],
         station_id=101104,
         interval=3600,
         timeStart='2020-06-12',
         timeEnd='2020-07-03',
         timezone="UTC",
         altitude=70,
         longitude=14.3711,
         latitude=67.2828,
         ViewDataFrame=True):

    response = ipm.get_weatheradapter(endpoint='/weatheradapter/fmi/',
                                      credentials=None,
                                      weatherStationId=station_id,
                                      timeStart=timeStart,
                                      timeEnd=timeEnd,
                                      interval=interval,
                                      parameters=parameters)

    times = pd.date_range(start=response['timeStart'].split('T')[0],
Beispiel #8
0
class WeatherDataHub:
    """
        Allows to access at IPM weather resources 
        give the list of weather adapter (resources) available on IPM and allows access to weather data source
        
        ..doctest::
        >>> wsh = WeatherDataHub()
        >>> wsh.list_resources()
        >>> wsh.get_resource(name = 'Finnish Meteorological Institute measured data')

    """
    def __init__(self):
        """
            Give an access to IPM interface from agroservice
        """
        self.ipm = IPM()
        self.sources = None
        self.local_sources = []

    @property
    def __resources__(self):

        if self.sources is None:
            self.sources = self.ipm.get_weatherdatasource()

        if len(self.local_sources) > 0:
            self.sources.append(self.local_sources)

        return {item["name"]: item for item in self.sources}

    @property
    def list_resources(self):
        """ display a dataframe of list of resources with their description 

        Returns
        -------
        pandas.DataFrame
            name and description of available weatherdatasource on IPM service
        """
        # if local:
        #     return list(self.local_sources)

        # else:
        df = pandas.DataFrame(self.__resources__).T.reset_index()
        df.rename({"index": "name"}, inplace=True)
        return df[["name", "description", "parameters"]]

    @property
    def parameters(self):
        ipm_parameter = self.ipm.get_parameter()
        return pandas.DataFrame.from_records(ipm_parameter)

    def __forecast__(self):
        return {
            key: bool(value["temporal"]["forecast"])
            for key, value in self.__resources__.items()
        }

    def __endpoint__(self):
        return {
            key: value["endpoint"]
            for key, value in self.__resources__.items()
        }

    def get_ressource(self, name: str):
        """ Get ressource from WeatherDataSource

        Parameters
        ----------
        name : str
             name of weatherdatasource (available in list ressource)

        Returns
        -------
        WeatherDataSource
           weatherdatasource with the name of resource

        Raises
        ------
        NotImplementedError
            the resource is unknown or the name of the resource is misspelled
        """
        if name in self.local_sources:
            return WeatherDataSource(name=name,
                                     forecast=None,
                                     endpoint=None,
                                     df=self.local_sources["endpoint"])
        else:
            keys = [item for item in self.__resources__]
            if name in keys:
                return WeatherDataSource(name,
                                         forecast=self.__forecast__()[name],
                                         endpoint=self.__endpoint__()[name])
            else:
                raise NotImplementedError(
                    "the resource is unknown or the name of the resource is misspelled"
                )

    def add_local_ressource(
        self,
        name,
        data,
        longitude=3.87,
        latitude=43.61,
        altitude=0,
        timezone="Europe/Paris",
        interval=3600,
        convert_name={
            'temperature_air': 1002,
            "relative_humidity": 3001,
            "rain": 2001,
            "wind_speed": 4005,
            "global_radiation": 5001
        }):

        data = data.rename(columns=convert_name)

        data.attrs = {
            "longitude": longitude,
            "latitude": latitude,
            "altitude": altitude,
            "timezone": timezone,
            "interval": interval
        }

        d = {
            "id": "personal data",
            "name": name,
            "description": "personal data",
            "public_URL": None,
            "endpoint": data,
            "authentication_type": None,
            "needs_data_control": False,
            "access_type": 'location',
            "priority": 0,
            "temporal": {
                "forecast": None,
                "historic": {
                    "start": data.index.tolist()[0].strftime('%Y-%m-%d'),
                    "end": data.index.tolist()[-1].strftime('%Y-%m-%d'),
                    "interval": [interval]
                }
            },
            "parameters": {
                'common': data.columns.tolist(),
                'optional': None
            },
            "spatial": None,
            "organization": None
        }

        self.local_sources = d
        return data

    def __data_reader__(
            self,
            path=r'C:\Users\mlabadie\Documents\GitHub\weatherdata\example\Boigneville_2012_2013_h.csv',
            sep=';',
            column_name=[
                'date', 'h', 'temperature_air', 'relative_humidity', 'rain',
                'wind_speed', 'global_radiation'
            ],
            skiprows=2,
            dec=","):
        r""" Reader for my data boignonville

        Parameters
        ----------
        path : regexp, optional
            file path, by default r'C:\Users\mlabadie\Documents\GitHub\weatherdata\example\Boigneville_2012_2013_h.csv'
        sep : str, optional
            type of separator in my data, by default ';'
        column_name : list, optional
            column_name of data, by default ['date', 'h', 'temperature_air', 'relative_humidity', 'rain', 'wind_speed', 'global_radiation']
        skiprows : int, optional
        line of data begin, by default 2
        dec : str, optional
            type of decimal used in my file, by default ","
        """
        data = pandas.read_csv(path,
                               names=column_name,
                               sep=';',
                               skiprows=skiprows,
                               decimal=dec,
                               encoding='latin-1')
        data.index = pandas.to_datetime(data['date'].map(str) + ' ' +
                                        data['h'],
                                        dayfirst=True)
        data['date'] = data.index

        # convert Rg J/cm2 -> J.m-2.s-1
        data['global_radiation'] *= (10000. / 3600)

        # convert Global radiation to PPFD -> µmol.m-2.s-1
        #data["Par"]=data["global_radiation"]*0.48*4.6

        # convert wind km/h -> m.s-1
        data['wind_speed'] *= (1000. / 3600)
        data = data.drop(columns=["date", "h"])

        return data
Beispiel #9
0
class WeatherDataSource:
    def __init__(self, name, forecast, endpoint, df=None):
        self.name = name
        self.forecast = forecast
        self.endpoint = endpoint
        self.sources = WeatherDataHub().__resources__
        self.ipm = IPM()
        self.df = df

        # WeatherDataHub.__init__(self)

    @property
    def __source__(self):

        # if self.sources is None:
        #     self.sources=self.__resources__

        source = self.sources[self.name]
        return source

    @property
    def parameter(self):
        df = WeatherDataHub().parameters
        list_parameters = self.__source__["parameters"]["common"]

        if self.__source__["parameters"]["optional"]:
            list_parameters.append(list_parameters)

        return df[df["id"].isin(list_parameters)]

    @property
    def stations(self):
        if "features" in json.loads(self.__source__["spatial"]["geoJSON"]):
            features = json.loads(
                self.__source__["spatial"]["geoJSON"])['features']

            #recupère les infos stations dans une properties
            stations = [feature["properties"] for feature in features]

            #recuperation et transformation des coordonnées
            coord_tmp = [
                feature['geometry']['coordinates'] for feature in features
            ]
            station_coords = [{
                "latitude": float(coord[0]),
                "longitude": float(coord[1])
            } for coord in coord_tmp]

            # ajoute les coordonnées dans stations
            for el in range(len(stations)):
                stations[el].update(station_coords[el])

            # affichage des stations comme dataframe
            df = pandas.DataFrame(stations)
            return df
        else:
            print(
                "No stations informations for this ressources \n the ressources asked in certainly a forcast \n please used longitude, latitude and altitude parameters to get data "
            )

    def data(self,
             parameters=[1002, 3002],
             stationId=[101104],
             timeStart='2020-06-12',
             timeEnd='2020-07-03',
             timeZone="UTC",
             altitude=[70.0],
             longitude=[14.3711],
             latitude=[67.2828],
             credentials=None,
             interval=3600,
             display='ds',
             varname='id',
             usecache=False,
             savecache=False):

        responses = []

        if self.forecast == False:
            times = pandas.date_range(timeStart,
                                      timeEnd,
                                      freq=str(interval) + 's',
                                      tz=timeZone)

            # time transformation for query format
            timeStart = times[0].strftime('%Y-%m-%dT%H:%M:%S')
            timeEnd = times[-1].strftime('%Y-%m-%dT%H:%M:%S')
            if times.tz._tzname == 'UTC':
                timeStart += 'Z'
                timeEnd += 'Z'
            else:
                decstr = times[0].strftime('%z')
                decstr = decstr[:-2] + ':' + decstr[-2:]
                timeStart += decstr
                timeEnd += decstr

            interval = pandas.Timedelta(times.freq).seconds

            for station in stationId:
                logging.info('start connecting to station %s' % station)
                path = os.path.join(
                    pathCache(),
                    str(station) + '_' + str(parameters) + "_" +
                    timeStart.split("T")[0] + "_" + timeEnd.split("T")[0] +
                    '.json')

                if usecache and os.path.exists(path):
                    with open(path) as f:
                        data = json.load(f)
                else:
                    data = self.ipm.get_weatheradapter(
                        endpoint=self.endpoint,
                        weatherStationId=station,
                        timeStart=timeStart,
                        timeEnd=timeEnd,
                        interval=interval,
                        parameters=parameters,
                        credentials=credentials)

                if type(data) is dict:
                    responses.append(data)
                elif type(data) is int:
                    logging.warning('HTTPError: %s for %s' % (data, station))

                if savecache and type(data) is dict:
                    with open(path, 'w') as f:
                        json.dump(data, f)

        elif self.endpoint in [
                "https://ipmdecisions.nibio.no/api/wx/rest/weatheradapter/dmipoint/",
                'https://ipmdecisions.nibio.no/api/wx/rest/weatheradapter/lantmet/'
        ]:
            stationId = None

            times = pandas.date_range(timeStart,
                                      timeEnd,
                                      freq=str(interval) + 'S',
                                      tz=timeZone)

            # time transformation for query format
            timeStart = times[0].strftime('%Y-%m-%dT%H:%M:%S')
            timeEnd = times[-1].strftime('%Y-%m-%dT%H:%M:%S')
            if times.tz._tzname == 'UTC':
                timeStart += 'Z'
                timeEnd += 'Z'
            else:
                decstr = times[0].strftime('%z')
                decstr = decstr[:-2] + ':' + decstr[-2:]
                timeStart += decstr
                timeEnd += decstr

            for el in range(len(latitude)):
                path = os.path.join(
                    pathCache(),
                    str(timeStart) + '_' + str(timeEnd) + '_' +
                    str(parameters) + str(altitude[el]) + '_' +
                    str(latitude[el]) + "_" + str(longitude[el]) + '.json')

                if usecache and os.path.exists(path):
                    with open(path) as f:
                        data = json.load(f)
                else:
                    data = self.ipm.get_weatheradapter_forecast(
                        endpoint=self.endpoint,
                        altitude=altitude[el],
                        latitude=latitude[el],
                        longitude=longitude[el],
                        timeStart=timeStart,
                        timeEnd=timeEnd,
                        interval=interval,
                        parameters=parameters)

                if type(data) is dict:
                    responses.append(data)
                elif type(data) is int:
                    logging.warning(
                        "HTTPError:%s for %s" %
                        (data, [altitude[el], latitude[el], longitude[el]]))

                if savecache and type(data) is dict:
                    with open(path, 'w') as f:
                        json.dump(data, f)
        else:
            stationId = None
            timeStart == None
            timeEnd == None
            interval = None
            for el in range(len(latitude)):
                path = os.path.join(
                    pathCache(),
                    str(altitude[el]) + '_' + str(latitude[el]) + "_" +
                    str(longitude[el]) + '.json')

                if usecache and os.path.exists(path):
                    with open(path) as f:
                        data = json.load(f)
                else:
                    data = self.ipm.get_weatheradapter_forecast(
                        endpoint=self.endpoint,
                        altitude=altitude[el],
                        latitude=latitude[el],
                        longitude=longitude[el])

                if type(data) is dict:
                    responses.append(data)
                elif type(data) is int:
                    logging.warning(
                        "HTTPError:%s for %s" %
                        (data, [altitude[el], latitude[el], longitude[el]]))

                if savecache and type(data) is dict:
                    with open(path, 'w') as f:
                        json.dump(data, f)

        if display == "ds":
            return self.__convert_xarray_dataset__(responses, stationId,
                                                   varname, display)
        else:
            return responses

    def __convert_xarray_dataset__(self, responses, stationId, varname,
                                   display):

        if display != "ds":
            return responses
        else:
            times = pandas.date_range(start=responses[0]["timeStart"],
                                      end=responses[0]["timeEnd"],
                                      freq=str(responses[0]["interval"]) + "S",
                                      name="time")

            #times.strftime('%Y-%m-%dT%H:%M:%S')

            datas = [
                np.array(
                    response['locationWeatherData'][0]['data']).astype("float")
                for response in responses
            ]

            dats = [[
                data[:, i].reshape(data.shape[0], 1)
                for i in range(data.shape[1])
            ] for data in datas]

            # construction of dict for dataset variable
            data_vars = [{
                str(response['weatherParameters'][i]): (['time',
                                                         'location'], dat[i])
                for i in range(len(response['weatherParameters']))
            } for response in responses for dat in dats]

            # construction dictionnaire coordonnée
            if stationId:
                coords = [
                    {
                        'time':
                        times.values,
                        'location': ([stationId[el]]),
                        'lat': ("location", [
                            float(responses[el]['locationWeatherData'][0]
                                  ['latitude'])
                        ]),
                        'lon': ("location", [
                            float(responses[el]['locationWeatherData'][0]
                                  ['longitude'])
                        ]),
                        #'alt':[float(responses[el]['locationWeatherData'][0]['altitude'])]
                    } for el in range(len(responses))
                ]

            else:
                coords = [
                    {
                        'time':
                        times.values,
                        'location': ([
                            str([
                                responses[el]['locationWeatherData'][0]
                                ['latitude'], responses[el]
                                ['locationWeatherData'][0]['longitude']
                            ])
                        ]),
                        'lat':
                        ('location',
                         [responses[el]['locationWeatherData'][0]['latitude']
                          ]),
                        'lon': ('location', [
                            responses[el]['locationWeatherData'][0]
                            ['longitude']
                        ]),
                        #'alt':[float(responses[el]['locationWeatherData'][0]['altitude'])]
                    } for el in range(len(responses))
                ]

            # list de ds
            list_ds = [
                xr.Dataset(data_vars[el], coords=coords[el])
                for el in range(len(responses))
            ]

            #merge ds
            ds = xr.merge(list_ds)

            #add coordinates attributes
            if stationId:
                ds.coords['time'].attrs["name"] = "time"
                ds.coords['location'].attrs['name'] = 'WeatherStationId'
                ds.coords['lat'].attrs['name'] = 'latitude'
                ds.coords['lat'].attrs['unit'] = 'degrees_north'
                ds.coords['lon'].attrs['name'] = 'longitude'
                ds.coords['lon'].attrs['unit'] = 'degrees_east'
            else:
                #ds.coords['location'].attrs['name']='[latitude,longitude]'
                ds.coords['lat'].attrs['name'] = 'latitude'
                ds.coords['lat'].attrs['unit'] = 'degrees_north'
                ds.coords['lon'].attrs['name'] = 'longitude'
                ds.coords['lon'].attrs['unit'] = 'degrees_east'

            # add data variable  attributes
            param = self.ipm.get_parameter()
            p = {
                str(item['id']): item
                for item in param
                if item['id'] in responses[0]['weatherParameters']
            }

            for el in list(ds.data_vars):
                try:
                    ds.data_vars[el].attrs = p[str(el)]
                except KeyError as e:
                    logging.exception(
                        "The weatherParameter not implemented; key error: %s".
                        format(e))

            # Attribute of dataset
            if stationId:
                ds.attrs['weatherRessource'] = self.name
                #ds.attrs['weatherStationId']=stationId
                ds.attrs['timeStart'] = str(ds.coords['time'].values[0])
                ds.attrs['timeEnd'] = str(ds.coords['time'].values[-1])
                ds.attrs['parameters'] = list(ds.data_vars)
            else:
                ds.attrs['weatherRessource'] = self.name
                ds.attrs['timeStart'] = str(ds.coords['time'].values[0])
                ds.attrs['timeEnd'] = str(ds.coords['time'].values[-1])
                ds.attrs['parameters'] = list(ds.data_vars)

            if varname == "name":
                ds = ds.rename_vars(
                    name_dict={
                        str(ds[el].attrs['id']): ds[el].attrs['name']
                        for el in list(ds.keys())
                    })

        return ds

    def __dataset_to_ipm__(self, ds: xr.Dataset):
        """Parser from dataset to weather ouput IPM format

        Parameters
        ----------
        ds : xr.Dataset
            weatherdata in xarray dataset format

        Returns
        -------
        dict
            IPM weather data from IPM weatherdata format
        """

        timeStart = pandas.to_datetime(ds.time.values[0])
        timesecondDate = pandas.to_datetime(ds.time.values[1])
        timeEnd = pandas.to_datetime(ds.time.values[-1])

        interval = timesecondDate - timeStart
        interval = interval.seconds

        timeStart = timeStart.strftime("%Y-%m-%dT%H:%M") + "Z"
        timeEnd = timeEnd.strftime("%Y-%m-%dT%H:%M") + "Z"

        # parser ipm format
        d = {
            "timeStart":
            timeStart,
            "timeEnd":
            timeEnd,
            "interval":
            interval,
            'weatherParameters': [int(el) for el in list(ds.data_vars)],
            "locationWeatherData": [{
                "longitude":
                float(ds.lon.values),
                "latitude":
                float(ds.lat.values),
                "altitude":
                0,
                "amalgamation":
                list(np.repeat(0, len(ds.data_vars))),
                "data":
                ds.to_dataframe().drop(
                    columns=['lat', 'lon']).to_numpy().tolist(),
                "qc":
                list(np.repeat(0, len(ds.data_vars))),
                "width":
                len(ds.data_vars),
                "length":
                len(ds.time)
            }]
        }
        return [d]

    def to_ipm(self, display="json"):
        """Convert weather dataframe into IPM weather output schema

        Parameters
        ----------
        longitude : float, optional
            longitudinal coordinate in degree of the weather dataframe, by default 3.87
        latitude : float, optional
            latitude coordinate in degree of the weather dataframe  , by default 43.61
        altitude : float, optional
            altitude coordinate in degree of the weather dataframe, by default 0.0
        timezone : str, optional
            time zone of dataframe eg. Europe/Paris if weatherdata is in france, by default "Europe/Paris"
        interval : int, optional
            interval time between index in second eg 3600 if weather data is in hour , by default 3600
        convert_name : dict, optional
            dict of conversion between weather dataframe and ipm parameters, by default {'temperature_air':1002, "relative_humidity":3001, "rain":2001, "wind_speed":4005, "global_radiation":5001}
        display : str, optional
            choose the type of data according json schema ipm or ds in xarray.dataset , by default "json"

        Returns
        -------
        json or xarray.dataset
            return data in weatherdata according to ipm input (json) or in xarray.dataset (ds)
        """

        data = self.endpoint
        time = pandas.date_range(
            start=data.index.tolist()[0],
            end=data.index.tolist()[-1],
            tz=data.attrs["timezone"],
            freq=str(data.attrs["interval"]) +
            "s").tz_convert("UTC").strftime('%Y-%m-%dT%H:%M:%S') + "Z"

        weather_ipm_schema = {}
        weather_ipm_schema["timeStart"] = time.tolist()[0]
        weather_ipm_schema["timeEnd"] = time.tolist()[-1]
        weather_ipm_schema["interval"] = data.attrs["interval"]
        weather_ipm_schema['weatherParameters'] = data.columns.to_list()
        weather_ipm_schema["locationWeatherData"] = [{
            "longitude":
            data.attrs["longitude"],
            "latitude":
            data.attrs["latitude"],
            "altitude":
            data.attrs["altitude"],
            "amalgamation":
            np.repeat(0, data.shape[1]).tolist(),
            "data":
            np.array(data).tolist(),
            "qc":
            np.repeat(0, data.shape[1]).tolist(),
            "width":
            data.shape[1],
            "length":
            data.shape[0]
        }]

        if display == "ds":
            return self.__convert_xarray_dataset__([weather_ipm_schema],
                                                   stationId=None,
                                                   varname="id",
                                                   display="ds")
        else:
            responses = weather_ipm_schema
        return [responses]

    def station_plot(self, ds=None, varname=None, time=None, resample=None):
        """_summary_

        Parameters
        ----------
        ds : xarray.Dataset
            xarray.dataset from weather ressources
        varname : str, optional
        variable name to plot, if None plot station localisation by default None
        time : int, optional
            index of time, by default None
        resample : str, optional
            frequency that data can be resampling. resampling calculate is mean function according ds.time eg d for days, by default None
        """
        ext_lat_min = int(ds.lat.values.min() - 1)
        ext_lat_max = int(ds.lat.values.max() + 1)
        ext_lon_min = int(ds.lon.values.min() - 1)
        ext_lon_max = int(ds.lon.values.max() + 1)

        if resample:
            ds = ds.resample(time=resample).mean()
        else:
            ds = ds

        df = ds.to_dataframe()
        fig = plt.figure(figsize=(12, 8))
        ax = fig.add_subplot(1, 1, 1, projection=ccrs.PlateCarree())
        ax.add_feature(cfea.LAKES, zorder=3)
        ax.add_feature(cfea.OCEAN, zorder=1)
        ax.add_feature(cfea.COASTLINE, zorder=2)
        ax.add_feature(cfea.LAND, zorder=1)
        ax.add_feature(cfea.BORDERS, zorder=4)
        ax.set_extent([ext_lon_min, ext_lon_max, ext_lat_min, ext_lat_max])
        gl = ax.gridlines(draw_labels=True, zorder=5)
        gl.right_labels = False
        gl.top_labels = False

        if (varname and time) is None:
            ax.scatter(x=df["lon"].values,
                       y=df["lat"].values,
                       transform=ccrs.PlateCarree(),
                       color='k',
                       s=10)
        else:
            ds.isel(time=time).plot.scatter(x='lon',
                                            y='lat',
                                            hue=varname,
                                            ax=ax,
                                            cmap='inferno',
                                            vmin=int(ds[varname].min()),
                                            vmax=int(ds[varname].max()),
                                            transform=ccrs.PlateCarree(),
                                            marker='s',
                                            s=50,
                                            add_guide=True,
                                            zorder=6)
        #ax.text(x=df["lon"].values,y=df["lat"].values,s=df.index.get_level_values("location"),color="k")
        # ax.text(x=float(ds.isel(time=0).lon.values)-0.5,y=float(ds.isel(time=0).lat.values),s=float(ds['1002'].isel(time=0).values),color="red")
        # ax.text(x=float(ds.isel(time=0).lon.values)-0.5,y=float(ds.isel(time=0).lat.values)-0.2,s=float(ds['3002'].isel(time=0).values),color="blue")

    def plot(self,
             ds=None,
             varname=None,
             location=None,
             resample=None,
             date=None):

        if resample:
            data = ds[varname].resample(time=resample).mean()

        else:
            data = ds[varname]

        if location is not None:
            data_loc = data.sel(location=location)
            data_loc.plot.line(x="time")
        else:
            data.plot.line(x="time")