#!/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/>.
#
########################################################################
"""
Objets natifs et convention de pyspc - Clés des collections de Série de données
"""
import pyspc.core.exception as _exception
from pyspc.core.timeutil import str2dt
[docs]
def str2tuple(s=None, sep=None, forceobs=False, forcesim=False):
"""
Convertir une chaine de caractères en tuple utilisé par pyspc.core.Series
Parameters
----------
s : str
Chaine de caractère à convertir
sep : str
Séparateur des champs. Défaut: '_'
forceobs : bool
Forcer la conversion en tant que série d'observation. Défaut: False
forcesim : bool
Forcer la conversion en tant que série de simulation. Défaut: False
L'option forceobs a la préséance sur forcesim
Returns
-------
tuple
Tuple servant de clé pour Series:
- observation : (identifiant, grandeur, None)
- simulation : (identifiant, grandeur, modele)
- prévision : (identifiant, grandeur, (runtime, model, scen, tend))
See Also
--------
pyspc.core.series.Series
Examples
--------
>>> from datetime import datetime as dt
>>> from pyspc.core.keyseries import str2tuple
Cas classiques
>>> str2tuple('ID_GRD')
('ID', 'GRD', None)
>>> str2tuple('ID_MDL_GRD')
('ID', 'GRD', 'MDL')
>>> str2tuple('ID_20210301_GRD')
('ID', 'GRD', (dt(2021, 3, 1, 0, 0), None, None, None))
>>> str2tuple('ID_20210301_MDL_GRD')
('ID', 'GRD', (dt(2021, 3, 1, 0, 0), 'MDL', None, None))
>>> str2tuple('ID_20210301_MDL_SCN_GRD')
('ID', 'GRD', (dt(2021, 3, 1, 0, 0), 'MDL', 'SCN', None))
>>> str2tuple('ID_20210301_MDL_SCN_INC_GRD')
('ID', 'GRD', (dt(2021, 3, 1, 0, 0), 'MDL', 'SCN', 'INC'))
>>> str2tuple('ID_2021030112_GRD')
('ID', 'GRD', (dt(2021, 3, 1, 12, 0), None, None, None))
>>> str2tuple('ID_2021030112_MDL_GRD')
('ID', 'GRD', (dt(2021, 3, 1, 12, 0), 'MDL', None, None))
>>> str2tuple('ID_2021030112_MDL_SCN_GRD')
('ID', 'GRD', (dt(2021, 3, 1, 12, 0), 'MDL', 'SCN', None))
>>> str2tuple('ID_2021030112_MDL_SCN_INC_GRD')
('ID', 'GRD', (dt(2021, 3, 1, 12, 0), 'MDL', 'SCN', 'INC'))
>>> str2tuple('ID_202103011230_GRD')
('ID', 'GRD', (dt(2021, 3, 1, 12, 30), None, None, None))
>>> str2tuple('ID_202103011230_MDL_GRD')
('ID', 'GRD', (dt(2021, 3, 1, 12, 30), 'MDL', None, None))
>>> str2tuple('ID_202103011230_MDL_SCN_GRD')
('ID', 'GRD', (dt(2021, 3, 1, 12, 30), 'MDL', 'SCN', None))
>>> str2tuple('ID_202103011230_MDL_SCN_INC_GRD')
('ID', 'GRD', (dt(2021, 3, 1, 12, 30), 'MDL', 'SCN', 'INC'))
Cas avec 'forceobs=True'
>>> str2tuple('ID_GRD', forceobs=True)
('ID', 'GRD', None)
>>> str2tuple('ID_MDL_GRD', forceobs=True)
('ID_MDL', 'GRD', None)
>>> str2tuple('ID_20210301_GRD', forceobs=True)
('ID_20210301', 'GRD', None)
>>> str2tuple('ID_20210301_MDL_GRD', forceobs=True)
('ID_20210301_MDL', 'GRD', None)
>>> str2tuple('ID_20210301_MDL_SCN_GRD', forceobs=True)
('ID_20210301_MDL_SCN', 'GRD', None)
>>> str2tuple('ID_20210301_MDL_SCN_INC_GRD', forceobs=True)
('ID_20210301_MDL_SCN_INC', 'GRD', None)
Cas avec 'forcesim=True'
>>> str2tuple('ID_GRD', forcesim=True)
('ID', 'GRD', None)
>>> str2tuple('ID_MDL_GRD', forcesim=True)
('ID', 'GRD', 'MDL')
>>> str2tuple('ID_20210301_GRD', forcesim=True)
('ID', 'GRD', '20210301')
>>> str2tuple('ID_20210301_MDL_GRD', forcesim=True)
('ID', 'GRD', '20210301_MDL')
>>> str2tuple('ID_20210301_MDL_SCN_GRD', forcesim=True)
('ID', 'GRD', '20210301_MDL_SCN')
>>> str2tuple('ID_20210301_MDL_SCN_INC_GRD', forcesim=True)
('ID', 'GRD', '20210301_MDL_SCN_INC')
"""
# -------------------------------------------------------------------------
# 0- Contrôles
# -------------------------------------------------------------------------
_exception.check_str(s)
_exception.check_bool(forceobs)
_exception.check_bool(forcesim)
if sep is None:
sep = '_'
_exception.check_str(sep)
# -------------------------------------------------------------------------
# 1- Grandeur
# -------------------------------------------------------------------------
# Ancienne version avec str contenant le chemin d'un fichier
# info = os.path.basename(os.path.splitext(s)[0]).split('_')
# Nouvelle version: traiter une chaine de caractère sans supposer str=path
info = s.split('_')
varname = info.pop(-1)
# -------------------------------------------------------------------------
# 2- Cas observation
# -------------------------------------------------------------------------
if forceobs or len(info) == 1:
return (sep.join(info), varname, None)
# -------------------------------------------------------------------------
# 3- Cas simulation
# -------------------------------------------------------------------------
code = info.pop(0)
try:
runtime = str2dt(info[0])
except (KeyError, ValueError):
runtime = None
if forcesim or runtime is None:
return (code, varname, sep.join(info))
# -------------------------------------------------------------------------
# 4- Cas prévision
# -------------------------------------------------------------------------
info.pop(0) # retirer runtime
if not info:
return (code, varname, (runtime, None, None, None))
model = info.pop(0)
if not info:
return (code, varname, (runtime, model, None, None))
scen = info.pop(0)
if not info:
return (code, varname, (runtime, model, scen, None))
uncert = info.pop(0)
if not info:
return (code, varname, (runtime, model, scen, uncert))
raise ValueError(
f"La chaine de caractère est mal formatée. Il reste '{info}'")
[docs]
def tuple2str(t=None, dtfmt=None, sep=None):
"""
Convertir un tuple utilisé par pyspc.core.Series en chaine de caractères
Parameters
----------
t : tuple
Tuple servant de clé pour Series:
- observation : (identifiant, grandeur, None)
- simulation : (identifiant, grandeur, modele)
- prévision : (identifiant, grandeur, (runtime, model, scen, tend))
sep : str
Séparateur des champs. Défaut: '_'
dtfmt : str
Format d'écriture des dates. Défaut: '%Y%m%d%H'
Returns
-------
s : str
Chaine de caractère à convertir
See Also
--------
pyspc.core.keyseries.str2tuple
Examples
--------
>>> from datetime import datetime as dt
>>> from pyspc.core.keyseries import tuple2str
Cas par défaut
>>> tuple2str(('ID', 'GRD', None))
ID_GRD
>>> tuple2str(('ID', 'GRD', 'MDL'))
ID_MDL_GRD
>>> tuple2str(('ID', 'GRD', (dt(2021, 3, 1, 0, 0), None, None, None)))
ID_2021030100_GRD
>>> tuple2str(('ID', 'GRD', (dt(2021, 3, 1, 0, 0), 'MDL', None, None)))
ID_2021030100_MDL_GRD
>>> tuple2str(('ID', 'GRD', (dt(2021, 3, 1, 0, 0), 'MDL', 'SCN', None)))
ID_2021030100_MDL_SCN_GRD
>>> tuple2str(('ID', 'GRD', (dt(2021, 3, 1, 0, 0), 'MDL', 'SCN', 'INC')))
ID_2021030100_MDL_SCN_INC_GRD
>>> tuple2str(('ID', 'GRD', (dt(2021, 3, 1, 12, 0), None, None, None)))
ID_2021030112_GRD
>>> tuple2str(('ID', 'GRD', (dt(2021, 3, 1, 12, 0), 'MDL', None, None)))
ID_2021030112_MDL_GRD
>>> tuple2str(('ID', 'GRD', (dt(2021, 3, 1, 12, 0), 'MDL', 'SCN', None)))
ID_2021030112_MDL_SCN_GRD
>>> tuple2str(('ID', 'GRD', (dt(2021, 3, 1, 12, 0), 'MDL', 'SCN', 'INC')))
ID_2021030112_MDL_SCN_INC_GRD
>>> tuple2str(('ID', 'GRD', (dt(2021, 3, 1, 13, 30), None, None, None)))
ID_2021030113_GRD
>>> tuple2str(('ID', 'GRD', (dt(2021, 3, 1, 13, 30), 'MDL', None, None)))
ID_2021030113_MDL_GRD
>>> tuple2str(('ID', 'GRD', (dt(2021, 3, 1, 13, 30), 'MDL', 'SCN', None)))
ID_2021030113_MDL_SCN_GRD
>>> tuple2str(('ID', 'GRD', (dt(2021, 3, 1, 13, 30), 'MDL', 'SCN', 'INC')))
ID_2021030113_MDL_SCN_INC_GRD
Cas avec 'dtfmt' définie par l'utilisateur
>>> tuple2str(('ID', 'GRD', (dt(2021, 3, 1, 0, 0), None, None, None)),
dtfmt='%Y%m%d%H%M')
ID_202103010000_GRD
>>> tuple2str(('ID', 'GRD', (dt(2021, 3, 1, 0, 0), 'MDL', None, None)),
dtfmt='%Y%m%d%H%M')
ID_202103010000_MDL_GRD
>>> tuple2str(('ID', 'GRD', (dt(2021, 3, 1, 0, 0), 'MDL', 'SCN', None)),
dtfmt='%Y%m%d%H%M')
ID_202103010000_MDL_SCN_GRD
>>> tuple2str(('ID', 'GRD', (dt(2021, 3, 1, 0, 0), 'MDL', 'SCN', 'INC')),
dtfmt='%Y%m%d%H%M')
ID_202103010000_MDL_SCN_INC_GRD
>>> tuple2str(('ID', 'GRD', (dt(2021, 3, 1, 12, 0), None, None, None)),
dtfmt='%Y%m%d%H%M')
ID_202103011200_GRD
>>> tuple2str(('ID', 'GRD', (dt(2021, 3, 1, 12, 0), 'MDL', None, None)),
dtfmt='%Y%m%d%H%M')
ID_202103011200_MDL_GRD
>>> tuple2str(('ID', 'GRD', (dt(2021, 3, 1, 12, 0), 'MDL', 'SCN', None)),
dtfmt='%Y%m%d%H%M')
ID_202103011200_MDL_SCN_GRD
>>> tuple2str(('ID', 'GRD', (dt(2021, 3, 1, 12, 0), 'MDL', 'SCN', 'INC')),
dtfmt='%Y%m%d%H%M')
ID_202103011200_MDL_SCN_INC_GRD
>>> tuple2str(('ID', 'GRD', (dt(2021, 3, 1, 12, 30), None, None, None)),
dtfmt='%Y%m%d%H%M')
ID_202103011230_GRD
>>> tuple2str(('ID', 'GRD', (dt(2021, 3, 1, 12, 30), 'MDL', None, None)),
dtfmt='%Y%m%d%H%M')
ID_202103011230_MDL_GRD
>>> tuple2str(('ID', 'GRD', (dt(2021, 3, 1, 12, 30), 'MDL', 'SCN', None)),
dtfmt='%Y%m%d%H%M')
ID_202103011230_MDL_SCN_GRD
>>> tuple2str(('ID', 'GRD', (dt(2021, 3, 1, 12, 30), 'MDL', 'SCN', 'INC')),
dtfmt='%Y%m%d%H%M')
ID_202103011230_MDL_SCN_INC_GRD
"""
# -------------------------------------------------------------------------
# 0- Contrôles
# -------------------------------------------------------------------------
_exception.check_listlike(t)
if dtfmt is None:
dtfmt = '%Y%m%d%H'
_exception.check_str(dtfmt)
if sep is None:
sep = '_'
_exception.check_str(sep)
# -------------------------------------------------------------------------
# 1- Identifiant et grandeur
# -------------------------------------------------------------------------
try:
code = t[0]
varname = t[1]
except IndexError as ie:
raise ValueError("Le tuple est mal-formaté. Impossible d'extraire "
"l'identifiant et/ou la grandeur") from ie
_exception.check_str(code)
_exception.check_str(varname)
try:
meta = t[2]
except IndexError:
meta = None
# -------------------------------------------------------------------------
# 2- Cas observation
# -------------------------------------------------------------------------
if meta is None:
return sep.join([code, varname])
# -------------------------------------------------------------------------
# 3- Cas simulation
# -------------------------------------------------------------------------
if isinstance(meta, str):
return sep.join([code, meta, varname])
# -------------------------------------------------------------------------
# 4- Cas prévision
# -------------------------------------------------------------------------
_exception.check_dt(meta[0])
meta = [x for x in meta if x is not None]
meta[0] = meta[0].strftime(dtfmt)
return sep.join([code, *meta, varname])