#!/usr/bin/python3
# -*- coding: utf-8 -*-
########################################################################
#
# This file is part of python module <pyspc>.
# Copyright (C) 2013-2021 R. Marty
# (renaud.marty@developpement-durable.gouv.fr)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program (see COPYING.txt).
# If not, see <http://www.gnu.org/licenses/>.
#
########################################################################
"""Bibliothèque pyspc du projet pyspc - IO - LAMEDO - read."""
from datetime import timedelta as td
import numpy as np
import pandas as pnd
from pyspc.core.keyseries import str2tuple, tuple2str
from pyspc.core.parameter import Parameter
from pyspc.core.serie import Serie
from pyspc.core.series import Series
import pyspc.core.exception as _exception
from pyspc.convention.lamedo import (
BDAPBP_SCENS, BDIMAGE_RATIOS, BDIMAGE_PREFIX)
from pyspc.data.lamedo import BdApbp, BdImage
PROVIDER = 'BdImage'
[docs]
def read_BdImage(filename=None, ratio_image=1, ratio_stats=1, warning=True):
"""
Créer une instance Series à partir de données BdImage.
Parameters
----------
filename : str
Nom du fichier d'observations de Météo-France
ratio_image : float
Ratio minimal requis pour les images
ratio_stats : float
Ratio minimal requis pour les statistiques
warning : bool
Imprimer les erreurs ?
Returns
-------
series : pyspc.core.series.Series
Collection de séries de données
Examples
--------
>>> from pyspc.io.lamedo import read_BdImage
Cas d'observations statistiques sur une zone
>>> f = 'data'/data/lamedo/getObsStatsByZones_antilope-j1-rr_000100.xml'
>>> series = read_BdImage(filename=f)
>>> series
*************************************
********** SERIES *******************
*************************************
* NOM DE LA COLLECTION = BdImage
* TYPE DE COLLECTION = obs
* NOMBRE DE SERIES = 14
* ----------------------------------
* SERIE #1
* - CODE = LO8060
* - VARNAME = PH
* - META = antilope,j1,rr,cvar
* ----------------------------------
* SERIE #2
* - CODE = LO8060
* - VARNAME = PH
* - META = antilope,j1,rr,etyp
* ----------------------------------
* SERIE #3
* - CODE = LO8060
* - VARNAME = PH
* - META = antilope,j1,rr,max
* ----------------------------------
* SERIE #4
* - CODE = LO8060
* - VARNAME = PH
* - META = antilope,j1,rr,med
* ----------------------------------
* SERIE #5
* - CODE = LO8060
* - VARNAME = PH
* - META = antilope,j1,rr,min
* ----------------------------------
* SERIE #6
* - CODE = LO8060
* - VARNAME = PH
* - META = antilope,j1,rr,moy
* ----------------------------------
* SERIE #7
* - CODE = LO8060
* - VARNAME = PH
* - META = antilope,j1,rr,q10
* ----------------------------------
* SERIE #8
* - CODE = LO8060
* - VARNAME = PH
* - META = antilope,j1,rr,q20
* ----------------------------------
* SERIE #9
* - CODE = LO8060
* - VARNAME = PH
* - META = antilope,j1,rr,q30
* ----------------------------------
* SERIE #10
* - CODE = LO8060
* - VARNAME = PH
* - META = antilope,j1,rr,q40
* ----------------------------------
* SERIE #11
* - CODE = LO8060
* - VARNAME = PH
* - META = antilope,j1,rr,q60
* ----------------------------------
* SERIE #12
* - CODE = LO8060
* - VARNAME = PH
* - META = antilope,j1,rr,q70
* ----------------------------------
* SERIE #13
* - CODE = LO8060
* - VARNAME = PH
* - META = antilope,j1,rr,q80
* ----------------------------------
* SERIE #14
* - CODE = LO8060
* - VARNAME = PH
* - META = antilope,j1,rr,q90
*************************************
Cas d'observations statistiques sur une zone avec application de ratios
>>> f = 'data'/data/lamedo/getObsStatsByZones_antilope-j1-rr_000100.xml'
>>> series = read_BdImage(filename=f, ratio_image=0.8, ratio_stats=0.8)
Avertissement : le ratio 'image' est inférieur au seuil de tolérance
(0.80 > 12/24=0.5) pour l'image detype=antilope, soustype=j1
et date=2021-05-09 06:00:00
Avertissement : le ratio 'stats' est inférieur au seuil de tolérance
(0.80 > 10/19=0.5263157894736842) pour la statistique deloc=LO8060
>>> series
*************************************
********** SERIES *******************
*************************************
* NOM DE LA COLLECTION = BdImage
* TYPE DE COLLECTION = obs
* NOMBRE DE SERIES = 14
* ----------------------------------
* SERIE #1
* - CODE = LO8060
* - VARNAME = PH
* - META = antilope,j1,rr,cvar
* ----------------------------------
* SERIE #2
* - CODE = LO8060
* - VARNAME = PH
* - META = antilope,j1,rr,etyp
* ----------------------------------
* SERIE #3
* - CODE = LO8060
* - VARNAME = PH
* - META = antilope,j1,rr,max
* ----------------------------------
* SERIE #4
* - CODE = LO8060
* - VARNAME = PH
* - META = antilope,j1,rr,med
* ----------------------------------
* SERIE #5
* - CODE = LO8060
* - VARNAME = PH
* - META = antilope,j1,rr,min
* ----------------------------------
* SERIE #6
* - CODE = LO8060
* - VARNAME = PH
* - META = antilope,j1,rr,moy
* ----------------------------------
* SERIE #7
* - CODE = LO8060
* - VARNAME = PH
* - META = antilope,j1,rr,q10
* ----------------------------------
* SERIE #8
* - CODE = LO8060
* - VARNAME = PH
* - META = antilope,j1,rr,q20
* ----------------------------------
* SERIE #9
* - CODE = LO8060
* - VARNAME = PH
* - META = antilope,j1,rr,q30
* ----------------------------------
* SERIE #10
* - CODE = LO8060
* - VARNAME = PH
* - META = antilope,j1,rr,q40
* ----------------------------------
* SERIE #11
* - CODE = LO8060
* - VARNAME = PH
* - META = antilope,j1,rr,q60
* ----------------------------------
* SERIE #12
* - CODE = LO8060
* - VARNAME = PH
* - META = antilope,j1,rr,q70
* ----------------------------------
* SERIE #13
* - CODE = LO8060
* - VARNAME = PH
* - META = antilope,j1,rr,q80
* ----------------------------------
* SERIE #14
* - CODE = LO8060
* - VARNAME = PH
* - META = antilope,j1,rr,q90
*************************************
Cas d'observations 'pixel' sur une bbox
>>> f = 'data'/data/lamedo/getObsValuesByBBox_antilope-j1-rr_010000.xml'
>>> series = read_BdImage(filename=f)
>>> series
*************************************
********** SERIES *******************
*************************************
* NOM DE LA COLLECTION = BdImage
* TYPE DE COLLECTION = obs
* NOMBRE DE SERIES = 4
* ----------------------------------
* SERIE #1
* - CODE = 793500.0,6412500.0
* - VARNAME = PJ
* - META = antilope,j1,rr,val
* ----------------------------------
* SERIE #2
* - CODE = 793500.0,6413500.0
* - VARNAME = PJ
* - META = antilope,j1,rr,val
* ----------------------------------
* SERIE #3
* - CODE = 794500.0,6412500.0
* - VARNAME = PJ
* - META = antilope,j1,rr,val
* ----------------------------------
* SERIE #4
* - CODE = 794500.0,6413500.0
* - VARNAME = PJ
* - META = antilope,j1,rr,val
*************************************
Cas d'observations 'pixel' sur une bbox - Température
>>> f = 'data'/data/lamedo/getObsValuesByBBox_sim-t-t.xml'
>>> series = read_BdImage(filename=f)
>>> series
*************************************
********** SERIES *******************
*************************************
* NOM DE LA COLLECTION = BdImage
* TYPE DE COLLECTION = obs
* NOMBRE DE SERIES = 6
* ----------------------------------
* SERIE #1
* - CODE = 779000.0,6404000.0
* - VARNAME = TI
* - META = sim,t,t,val
* ----------------------------------
* SERIE #2
* - CODE = 779000.0,6412000.0
* - VARNAME = TI
* - META = sim,t,t,val
* ----------------------------------
* SERIE #3
* - CODE = 779000.0,6420000.0
* - VARNAME = TI
* - META = sim,t,t,val
* ----------------------------------
* SERIE #4
* - CODE = 787000.0,6404000.0
* - VARNAME = TI
* - META = sim,t,t,val
* ----------------------------------
* SERIE #5
* - CODE = 787000.0,6412000.0
* - VARNAME = TI
* - META = sim,t,t,val
* ----------------------------------
* SERIE #6
* - CODE = 787000.0,6420000.0
* - VARNAME = TI
* - META = sim,t,t,val
*************************************
Cas de prévisions statistiques sur une zone
>>> f = 'data'/data/lamedo/getPrevByNetworkStatsByZones_pprod-rr-total.xml'
>>> series = read_BdImage(filename=f)
>>> series
*************************************
********** SERIES *******************
*************************************
* NOM DE LA COLLECTION = BdImage
* TYPE DE COLLECTION = fcst
* NOMBRE DE SERIES = 1
* ----------------------------------
* SERIE #1
* - CODE = LO850
* - VARNAME = PH
* - META = 2025-09-21 00:00:00+00:00, pprod, rr,total, moy
*************************************
Cas de prévisions 'pixel' sur une bbox
>>> f = 'data'/data/lamedo/getPrevByNetworkValuesByBBox_pprod-rr-total.xml'
>>> series = read_BdImage(filename=f)
>>> series
*************************************
********** SERIES *******************
*************************************
* NOM DE LA COLLECTION = BdImage
* TYPE DE COLLECTION = fcst
* NOMBRE DE SERIES = 4
* ----------------------------------
* SERIE #1
* - CODE = 793500.0,6412500.0
* - VARNAME = PH
* - META = 2025-09-21 00:00:00+00:00, pprod, rr,total, val
* ----------------------------------
* SERIE #2
* - CODE = 793500.0,6413500.0
* - VARNAME = PH
* - META = 2025-09-21 00:00:00+00:00, pprod, rr,total, val
* ----------------------------------
* SERIE #3
* - CODE = 794500.0,6412500.0
* - VARNAME = PH
* - META = 2025-09-21 00:00:00+00:00, pprod, rr,total, val
* ----------------------------------
* SERIE #4
* - CODE = 794500.0,6413500.0
* - VARNAME = PH
* - META = 2025-09-21 00:00:00+00:00, pprod, rr,total, val
*************************************
"""
# -------------------------------------------------------------------------
# 0- Contrôles
# -------------------------------------------------------------------------
_exception.check_str(filename)
_exception.check_numeric(ratio_image)
_exception.check_numeric(ratio_stats)
_exception.check_bool(warning)
provider = 'BdImage'
# -------------------------------------------------------------------------
# 1- Lecture
# -------------------------------------------------------------------------
# Création du lecteur
reader = BdImage(filename=filename)
# Lecture des données
try:
content = reader.read()
except Exception:
_exception.Warning(
None,
f"Formattage XML incorrect pour le fichier {filename}")
return None
# -------------------------------------------------------------------------
# 2- Contrôles du contenu XML
# -------------------------------------------------------------------------
_exception.raise_valueerror(
content.report.status != 0,
"Le fichier XML de BdImage est incorrect : statut != 0")
# -------------------------------------------------------------------------
# 3- Informations sur la requête
# -------------------------------------------------------------------------
requestname = content.report.request['request']
# -------------------------------------------------------------------------
# 4- Traitement du XML et transformation en Series
# -------------------------------------------------------------------------
if requestname.startswith('getObs'):
return _convert_bdimage_obs(
content=content, provider=provider,
ratio_image=ratio_image, ratio_stats=ratio_stats,
warning=warning)
if requestname.startswith('getPrev'):
return _convert_bdimage_prv(
content=content, provider=provider,
ratio_image=ratio_image, ratio_stats=ratio_stats,
warning=warning)
raise NotImplementedError(
"Le traitement de la requête {} n'est pas implémenté")
def _convert_bdimage_obs(content=None, provider=None,
ratio_image=None, ratio_stats=None, warning=True):
"""Convertir des données OBS de BdImage en pandas.DataFrame."""
# -------------------------------------------------------------------------
# 0- Initialisation de la collection
# -------------------------------------------------------------------------
series = Series(datatype='obs', name='BdImage')
# -------------------------------------------------------------------------
# 1- Images d'observation
# -------------------------------------------------------------------------
dfs = []
for image in content.observations:
df = __convert_bdimage_image(
image, ratio_image=ratio_image, ratio_stats=ratio_stats)
if df is None:
continue
dfs.append(df)
try:
df = pnd.concat(dfs, ignore_index=True)
except ValueError: # Aucune série extraite
return None
# -------------------------------------------------------------------------
# 2- Transformation du DataFrame
# -------------------------------------------------------------------------
df = df.set_index(keys=['LOC', 'FAMILY', 'KIND', 'BAND', 'DEPTH',
'RUNTIME', 'VALIDTIME'])
df = df.unstack(
level=['LOC', 'FAMILY', 'KIND', 'BAND', 'DEPTH', 'RUNTIME'])
df = df.sort_index(axis=0)
df = df.sort_index(axis=1)
# -------------------------------------------------------------------------
# 3- Création des séries
# -------------------------------------------------------------------------
for c in df.columns:
img = '_'.join(c[2:5])
df[c] = df[c] * BDIMAGE_RATIOS[img][0]
dfc = df[c].to_frame()
try:
target = c[5].to_pytimedelta()
param = Parameter.find(
prefix=BDIMAGE_PREFIX[img],
timedelta=target if target != td(seconds=0) else None)
except KeyError:
if warning:
_exception.Warning(
None,
f"La grandeur de la série '{c}' est inconnue. "
"Elle est ignorée")
continue
else:
varname = param.spc_varname
key = (c[1], varname, '_'.join([img, c[0]]).replace('_', ','))
# Si journalier: retirer heure et soustraire 1 jour
# BdImage: date = fin cumul
# pyspc: date = jour du cumul
if param.timestep == td(days=1):
dfc.index = dfc.index.normalize() - param.timestep
serie = Serie(dfc, code=key[0], varname=varname,
provider=provider, warning=warning)
series.add(serie, meta=key[2])
return series
def __convert_bdimage_image(image, ratio_image=1, ratio_stats=1, isobs=True):
"""Extraire les informations Image du fichier XML BdImage."""
_exception.check_bool(isobs)
_exception.check_numeric(ratio_image)
_exception.check_numeric(ratio_stats)
# -------------------------------------------------------------------------
# 0- Information sur l'image
# -------------------------------------------------------------------------
family = image.specie.family
kind = image.specie.kind
depth = image.depth # image.specie.depth : pas de temps nominal de l'img
validtime = image.date
if isobs:
runtime = None
else:
runtime = image.network
if image.ratio.value < ratio_image:
_exception.Warning(
None,
"le ratio 'image' est inférieur au seuil de tolérance "
f"({ratio_image:.2f} > "
f"{image.ratio.numerator:d}/{image.ratio.denominator:d}="
f"{image.ratio.value:.2f}) pour l'image de "
f"type={family}, soustype={kind} et date={validtime}"
)
return None
# -------------------------------------------------------------------------
# 1- Bandes de l'image
# -------------------------------------------------------------------------
dfs = []
for band in image.bands:
df = __convert_bdimage_band(band, ratio_stats=ratio_stats)
if df is None:
continue
df['FAMILY'] = family
df['KIND'] = kind
df['DEPTH'] = depth
df['VALIDTIME'] = validtime
df['RUNTIME'] = runtime
dfs.append(df)
if dfs:
return pnd.concat(dfs, ignore_index=True)
return None
def __convert_bdimage_band(band, ratio_stats=1):
"""Extraire les informations Bande du fichier XML BdImage."""
dfs = []
# -------------------------------------------------------------------------
# 0- Information sur la bande
# -------------------------------------------------------------------------
name = band.name
# -------------------------------------------------------------------------
# 1- Statistiques
# -------------------------------------------------------------------------
if band.stats:
for stat in band.stats:
df = __convert_bdimage_stats(stat, ratio_stats=ratio_stats)
if df is None:
continue
df['BAND'] = name
dfs.append(df.reset_index())
if dfs:
return pnd.concat(dfs, ignore_index=True)
return None
# -------------------------------------------------------------------------
# 2- Valeurs
# -------------------------------------------------------------------------
if band.samples:
for sample in band.samples:
df = __convert_bdimage_samples(sample)
if df is None:
continue
df['BAND'] = name
dfs.append(df.reset_index())
if dfs:
return pnd.concat(dfs, ignore_index=True)
return None
return None
def __convert_bdimage_samples(sample):
"""Extraire les informations Values du fichier XML BdImage."""
# -------------------------------------------------------------------------
# 1- Valeurs
# -------------------------------------------------------------------------
df = pnd.DataFrame(
sample.samples, index=[f"{xy[0]},{xy[1]}" for xy in sample.pixels])
df.index.name = 'LOC'
df.columns = ['val']
return df
def __convert_bdimage_stats(stat, ratio_stats=1):
"""Extraire les informations Stats du fichier XML BdImage."""
# -------------------------------------------------------------------------
# 0- Information sur la statistique
# -------------------------------------------------------------------------
loc = stat.zone
if stat.stat.ratio.value < ratio_stats:
_exception.Warning(
None,
f"le ratio 'stats' est inférieur au seuil de tolérance "
f"({ratio_stats:.2f} > "
f"{stat.stat.ratio.numerator:d}/{stat.stat.ratio.denominator:d}"
f"={stat.stat.ratio.denominator:.2f}) pour la "
f"statistique de {loc=}"
)
return None
# -------------------------------------------------------------------------
# 1- Statistiques
# -------------------------------------------------------------------------
df = pnd.DataFrame(stat.stat, index=[loc])
df.index.name = 'LOC'
df = df.replace([np.inf, -np.inf], np.nan)
return df
def _convert_bdimage_prv(content=None, provider=None,
ratio_image=None, ratio_stats=None, warning=True):
"""Convertir des données PREV de BdImage en pandas.DataFrame."""
# -------------------------------------------------------------------------
# 0- Initialisation de la collection
# -------------------------------------------------------------------------
series = Series(datatype='fcst', name='BdImage')
# -------------------------------------------------------------------------
# 1- Images de prévisions
# -------------------------------------------------------------------------
dfs = []
for prev in content.previsions:
for image in prev.images:
df = __convert_bdimage_image(
image, ratio_image=ratio_image, ratio_stats=ratio_stats,
isobs=False)
if df is None:
continue
dfs.append(df)
try:
df = pnd.concat(dfs, ignore_index=True)
except ValueError: # Aucune série extraite
return None
# -------------------------------------------------------------------------
# 2- Transformation du DataFrame
# -------------------------------------------------------------------------
df = df.set_index(keys=['LOC', 'FAMILY', 'KIND', 'BAND', 'DEPTH',
'RUNTIME', 'VALIDTIME'])
df = df.unstack(
level=['LOC', 'FAMILY', 'KIND', 'BAND', 'DEPTH', 'RUNTIME'])
df = df.sort_index(axis=0)
df = df.sort_index(axis=1)
# -------------------------------------------------------------------------
# 3- Création des séries
# -------------------------------------------------------------------------
for c in df.columns:
img = '_'.join(c[2:5])
df[c] = df[c] * BDIMAGE_RATIOS[img][0]
try:
target = c[5].to_pytimedelta()
param = Parameter.find(
prefix=BDIMAGE_PREFIX[img],
timedelta=target if target != td(seconds=0) else None)
except KeyError:
if warning:
_exception.Warning(
None,
f"La grandeur de la série '{c}' est inconnue. "
"Elle est ignorée")
continue
else:
varname = param.spc_varname
key = (c[1], varname,
(c[6].to_pydatetime(), c[2], c[3] + ',' + c[4], c[0]))
keystr = str2tuple(tuple2str(key), forceobs=True)
serie = Serie(df[c].to_frame(), code=keystr[0], varname=varname,
provider=provider, warning=warning)
series.add(serie, code=c[1], meta=key[2])
return series
[docs]
def read_BdApbp(filename=None, zones=None, warning=True):
"""
Créer une instance Series à partir de prévisions BdApbp.
Parameters
----------
filename : str
Nom du fichier prévisions BdApbp
zones : list
Liste des identifiants des zones à conserver.
Par défaut, toutes les zones sont retenues
warning : bool
Imprimer les erreurs ?
Returns
-------
series : pyspc.core.series.Series
Collection de séries de données
Examples
--------
>>> from pyspc.io.lamedo import read_BdApbp
Cas d'un fichier au format 'short'
>>> f = 'data/data/lamedo/bp_short.json'
>>> series = read_BdApbp(filename=f)
>>> series
*************************************
********** SERIES *******************
*************************************
* NOM DE LA COLLECTION = BdApbp
* TYPE DE COLLECTION = fcst
* NOMBRE DE SERIES = 8
* ----------------------------------
* SERIE #1
* - CODE = 41003
* - VARNAME = PJ
* - META = 2020-06-12 06:00:00, BdApbp, MoyInf
* ----------------------------------
* SERIE #2
* - CODE = 41005
* - VARNAME = PJ
* - META = 2020-06-12 06:00:00, BdApbp, MoyInf
* ----------------------------------
* SERIE #3
* - CODE = 41003
* - VARNAME = PJ
* - META = 2020-06-12 06:00:00, BdApbp, MoySup
* ----------------------------------
* SERIE #4
* - CODE = 41005
* - VARNAME = PJ
* - META = 2020-06-12 06:00:00, BdApbp, MoySup
* ----------------------------------
* SERIE #5
* - CODE = 41003
* - VARNAME = PJ
* - META = 2020-06-12 06:00:00, BdApbp, LocInf
* ----------------------------------
* SERIE #6
* - CODE = 41005
* - VARNAME = PJ
* - META = 2020-06-12 06:00:00, BdApbp, LocInf
* ----------------------------------
* SERIE #7
* - CODE = 41003
* - VARNAME = PJ
* - META = 2020-06-12 06:00:00, BdApbp, LocSup
* ----------------------------------
* SERIE #8
* - CODE = 41005
* - VARNAME = PJ
* - META = 2020-06-12 06:00:00, BdApbp, LocSup
*************************************
Cas d'un fichier au format 'short' avec sélection de zones
>>> f = 'data/data/lamedo/bp_short.json'
>>> series = read_BdApbp(filename=f, zones=['41005'])
>>> series
*************************************
********** SERIES *******************
*************************************
* NOM DE LA COLLECTION = BdApbp
* TYPE DE COLLECTION = fcst
* NOMBRE DE SERIES = 4
* ----------------------------------
* SERIE #1
* - CODE = 41005
* - VARNAME = PJ
* - META = 2020-06-12 06:00:00, BdApbp, MoyInf
* ----------------------------------
* SERIE #2
* - CODE = 41005
* - VARNAME = PJ
* - META = 2020-06-12 06:00:00, BdApbp, MoySup
* ----------------------------------
* SERIE #3
* - CODE = 41005
* - VARNAME = PJ
* - META = 2020-06-12 06:00:00, BdApbp, LocInf
* ----------------------------------
* SERIE #4
* - CODE = 41005
* - VARNAME = PJ
* - META = 2020-06-12 06:00:00, BdApbp, LocSup
*************************************
Cas d'un fichier au format 'long'
>>> f = 'data/data/lamedo/bp_long.json'
>>> series = read_BdApbp(filename=f, zones=['41005'])
>>> series
*************************************
********** SERIES *******************
*************************************
* NOM DE LA COLLECTION = BdApbp
* TYPE DE COLLECTION = fcst
* NOMBRE DE SERIES = 8
* ----------------------------------
* SERIE #1
* - CODE = 41003
* - VARNAME = PJ
* - META = 2020-06-12 05:26:00, BdApbp, MoyInf
* ----------------------------------
* SERIE #2
* - CODE = 41005
* - VARNAME = PJ
* - META = 2020-06-12 05:26:00, BdApbp, MoyInf
* ----------------------------------
* SERIE #3
* - CODE = 41003
* - VARNAME = PJ
* - META = 2020-06-12 05:26:00, BdApbp, MoySup
* ----------------------------------
* SERIE #4
* - CODE = 41005
* - VARNAME = PJ
* - META = 2020-06-12 05:26:00, BdApbp, MoySup
* ----------------------------------
* SERIE #5
* - CODE = 41003
* - VARNAME = PJ
* - META = 2020-06-12 05:26:00, BdApbp, LocInf
* ----------------------------------
* SERIE #6
* - CODE = 41005
* - VARNAME = PJ
* - META = 2020-06-12 05:26:00, BdApbp, LocInf
* ----------------------------------
* SERIE #7
* - CODE = 41003
* - VARNAME = PJ
* - META = 2020-06-12 05:26:00, BdApbp, LocSup
* ----------------------------------
* SERIE #8
* - CODE = 41005
* - VARNAME = PJ
* - META = 2020-06-12 05:26:00, BdApbp, LocSup
*************************************
"""
# -------------------------------------------------------------------------
# 0- Contrôles
# -------------------------------------------------------------------------
_exception.check_str(filename)
if zones is not None:
_exception.check_listlike(zones)
_exception.check_bool(warning)
# -------------------------------------------------------------------------
# 1- Lecture
# -------------------------------------------------------------------------
# Création du lecteur
reader = BdApbp(filename=filename)
# Lecture des données
df = reader.read()
# -------------------------------------------------------------------------
# 2- Transformation du DataFrame
# -------------------------------------------------------------------------
# Récupération du format du BP
datatype = reader._datatype
# Récupérer les dates de production par zone
runtimes = {x[0]: x[1].to_pydatetime()
for x in df[['CODE', 'DTPROD']].values}
# Définir BP[Moy,Loc][Inf,Sup]
col = df.apply(list_values, axis=1)
df = df.assign(VALUE=col.values) # VALUE : colonne avec les 4 valeurs
df[BDAPBP_SCENS] = pnd.DataFrame(df.VALUE.to_list(), index=df.index)
# Colonne 'DATE' -> Index
df = df.set_index(keys='DATE', drop=True)
df.index = [i - td(days=1) for i in df.index]
# Nettoyer les colonnes superflues
df = df.drop(columns=['NAME', 'DTPROD', # 'DATE',
'MOY', 'DELTA', 'LOC', 'LOCDELTA', 'VALUE'])
# Colonne 'Code' -> Multi-Index (None, Code) avec None: ['Debit (l/s)']
df = df.pivot(columns='CODE')
# MultiIndex : (CODE, VAR)
df.columns = df.columns.swaplevel()
# -------------------------------------------------------------------------
# 3- Conversion en Series
# -------------------------------------------------------------------------
series = Series(datatype='fcst', name='BdApbp')
for c in df.columns:
zone = c[0]
if isinstance(zones, list) and zone not in zones:
continue
scen = c[1]
runtime = runtimes[zone]
d = df[c].to_frame()
try:
serie = Serie(d, code=zone, provider='BdApbp', varname=datatype,
warning=warning)
except ValueError:
continue
series.add(serie=serie, meta=(runtime, 'BdApbp', scen))
return series
def list_values(row):
"""
Définir les valeurs 'MoyInf', 'MoySup', 'LocInf', 'LocSup'.
Selon les colonnes 'MOY', 'DELTA', 'LOC', 'LOCDELTA'
Parameters
----------
row : pandas.Series
Ligne d'un tableau de données
Returns
-------
list
Valeurs 'MoyInf', 'MoySup', 'LocInf', 'LocSup'
"""
ratio = 0.1 # 1/10 mm => mm
md = row['DELTA']
if np.isnan(md) or md is None:
md = 0
ld = row['LOCDELTA']
if np.isnan(ld) or ld is None:
ld = 0
mi = ratio * (row['MOY'] - md)
ms = ratio * (row['MOY'] + md)
li = ratio * (row['LOC'] - ld)
ls = ratio * (row['LOC'] + ld)
return [mi, ms, li, ls]
def set_ltime(row):
"""
Définir l'échéance en fonction de la date cible et de la date de prod.
Parameters
----------
row : pandas.Series
Ligne d'un tableau de données
Returns
-------
int
Echéance de la prévision
"""
ref = row['DTPROD']
target = row['DATE']
ltime = int((target - ref) / td(days=1))
return ltime