Code source de pyspc.data.sandre.sandre

#!/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/>.
#
########################################################################
"""
Données d'observation et de prévision - XML Sandre
"""
from collections import namedtuple
from datetime import datetime as dt
from xml.etree import ElementTree

from pyspc.convention.sandre import DATATYPES, FCST_COLS, OBS_COLS
import pyspc.core.exception as _exception

DATATYPES = sorted([d
                    for d in DATATYPES
                    if d.startswith('data')
                    or d.startswith('level')
                    or d.startswith('flow')])

ComSimul = namedtuple(
    'ComSimul', ['runtime', 'code', 'name'], defaults=[None, None, None])


[docs] class Sandre(): """Structure liée aux données XML Sandre."""
[docs] def __init__(self, filename=None): """ Initialisation de l'instance de la classe XML Sandre. Parameters ---------- filename : str Fichier local au format XML """ self.filename = filename
def __str__(self): """Afficher les données de l'instance XML Sandre.""" text = """ ************************************* *********** XML Sandre - Data ******* ************************************* * FICHIER = {filename} ************************************* """ return text.format(**vars(self))
[docs] def read(self): """ Lire le fichier XML du Sandre. Examples -------- >>> import pyspc.data.sandre as _sandre Exemple d'observations hydro (Q) >>> f = 'data/data/sandre/dataobs_hydro_Q.xml' >>> sandre = _sandre.Sandre(filename=f) >>> content = sandre.read() >>> content Message du 2016-05-13 13:41:49 de version 1.1 Emetteur: Intervenant SANDRE 1537::<sans nom> [0 contact] [None] Destinataire: Intervenant SIRET 13000930100016::<sans nom> [1 contact] [Contact 398::<sans civilite> <sans nom> <sans prenom> [intervenant 13000930100016]] Contenu: 0 intervenants 0 siteshydro 0 sitesmeteo 0 seuilshydro 0 seuilsmeteo 0 modelesprevision 0 evenements 0 courbestarage 0 jaugeages 0 courbescorrection 3 serieshydro 0 seriesmeteo 0 seriesobselab 0 simulations >>> for s in content.serieshydro: ... print(s.entite.code, s.grandeur) ... print(s.observations) res mth qal cnt statut dte 2016-04-17 01:00:00 45267.567568 8 16 0 4 2016-04-17 02:00:00 47105.405405 8 16 0 4 2016-04-17 03:00:00 48497.333333 8 16 0 4 2016-04-17 04:00:00 50470.666667 8 16 0 4 2016-04-17 05:00:00 50964.000000 8 16 0 4 2016-04-17 06:00:00 51950.666667 8 16 0 4 2016-04-17 07:00:00 52444.000000 8 16 0 4 2016-04-17 08:00:00 52444.000000 8 16 0 4 2016-04-17 09:00:00 52937.333333 8 16 0 4 2016-04-17 10:00:00 53430.666667 8 16 0 4 2016-04-17 11:00:00 53924.000000 8 16 0 4 2016-04-17 12:00:00 54417.333333 8 16 0 4 2016-04-17 13:00:00 54417.333333 8 16 0 4 2016-04-17 14:00:00 55404.000000 8 16 0 4 2016-04-17 15:00:00 56390.666667 8 16 0 4 2016-04-17 16:00:00 57377.333333 8 16 0 4 2016-04-17 17:00:00 58364.000000 8 16 0 4 2016-04-17 18:00:00 59350.666667 8 16 0 4 2016-04-17 19:00:00 60540.000000 8 16 0 4 2016-04-17 20:00:00 60540.000000 8 16 0 4 2016-04-17 21:00:00 60540.000000 8 16 0 4 2016-04-17 22:00:00 60540.000000 8 16 0 4 2016-04-17 23:00:00 60540.000000 8 16 0 4 res mth qal cnt statut dte 2016-04-18 59350.666667 8 16 0 4 res mth qal cnt statut dte 2016-04-18 01:00:00 58857.333333 8 16 0 4 2016-04-18 02:00:00 58364.000000 8 16 0 4 2016-04-18 03:00:00 57870.666667 8 16 0 4 2016-04-18 04:00:00 56884.000000 8 16 0 4 2016-04-18 05:00:00 56390.666667 8 16 0 4 2016-04-18 06:00:00 55404.000000 8 16 0 4 2016-04-18 07:00:00 54417.333333 8 16 0 4 2016-04-18 08:00:00 53430.666667 8 16 0 4 2016-04-18 09:00:00 52937.333333 8 16 0 4 2016-04-18 10:00:00 50470.666667 8 16 0 4 2016-04-18 11:00:00 52444.000000 8 16 0 4 2016-04-18 12:00:00 50964.000000 8 16 0 4 2016-04-18 13:00:00 49484.000000 8 16 0 4 2016-04-18 14:00:00 48990.666667 8 16 0 4 2016-04-18 15:00:00 48497.333333 8 16 0 4 2016-04-18 16:00:00 48024.324324 8 16 0 4 2016-04-18 17:00:00 47105.405405 8 16 0 4 2016-04-18 18:00:00 46186.486486 8 16 0 4 2016-04-18 19:00:00 45727.027027 8 16 0 4 2016-04-18 20:00:00 44808.108108 8 16 0 4 2016-04-18 21:00:00 44348.648649 8 16 0 4 2016-04-18 22:00:00 43429.729730 8 16 0 4 2016-04-18 23:00:00 42510.810811 8 16 0 4 Exemple d'observations élaborées hydro (Q) >>> f = 'data/data/sandre/K0550010_198009060000_198010060000_Q_obs.xml' >>> sandre = _sandre.Sandre(filename=f) >>> content = sandre.read() >>> content Message du 2021-11-08 16:46:41 de version 1.1 Emetteur: Intervenant SANDRE 1537::<sans nom> [0 contact] [None] Destinataire: Intervenant SANDRE 1528::<sans nom> [1 contact] [Contact 398::<sans civilite> <sans nom> <sans prenom> [intervenant 1528]] Contenu: 0 intervenants 0 siteshydro 0 sitesmeteo 0 seuilshydro 0 seuilsmeteo 0 modelesprevision 0 evenements 0 courbestarage 0 jaugeages 0 courbescorrection 0 serieshydro 0 seriesmeteo 1 seriesobselab 0 simulations >>> for s in content.seriesobselab: ... print(s.entite.code, s.typegrd) ... print(s.observations) K0550010 QmnJ res mth qal cnt statut dte 1980-09-06 11100.0 12 20 0 16 1980-09-07 11600.0 12 20 0 16 1980-09-08 9600.0 12 20 0 16 1980-09-09 11600.0 12 20 0 16 1980-09-10 12200.0 12 20 0 16 1980-09-11 12700.0 12 20 0 16 1980-09-12 10600.0 12 20 0 16 1980-09-13 10600.0 12 20 0 16 1980-09-14 9600.0 12 20 0 16 1980-09-15 8650.0 12 20 0 16 1980-09-16 8650.0 12 20 0 16 1980-09-17 7750.0 12 20 0 16 1980-09-18 7750.0 12 20 0 16 1980-09-19 7750.0 12 20 0 16 1980-09-20 5750.0 12 20 0 16 1980-09-21 770000.0 12 20 0 16 1980-09-22 392000.0 12 20 0 16 1980-09-23 120000.0 12 20 0 16 1980-09-24 81000.0 12 20 0 16 1980-09-25 56500.0 12 20 0 16 1980-09-26 47400.0 12 20 0 16 1980-09-27 41500.0 12 20 0 16 1980-09-28 34500.0 12 20 0 16 1980-09-29 30900.0 12 20 0 16 1980-09-30 84500.0 12 20 0 16 1980-10-01 26200.0 12 20 0 16 1980-10-02 24400.0 12 20 0 16 1980-10-03 23800.0 12 20 0 16 1980-10-04 23200.0 12 20 0 16 1980-10-05 23200.0 12 20 0 16 1980-10-06 22600.0 12 20 0 16 Exemple de prévision hydro >>> f = 'data/data/sandre/datafcst_hydro.xml' >>> sandre = _sandre.Sandre(filename=f) >>> content = sandre.read() >>> content Message du 2016-05-13 13:42:25 de version 1.1 Emetteur: Intervenant SANDRE 1537::<sans nom> [0 contact] [None] Destinataire: Intervenant SIRET 13000930100016::<sans nom> [1 contact] [Contact 398::<sans civilite> <sans nom> <sans prenom> [intervenant 13000930100016]] Contenu: 0 intervenants 0 siteshydro 0 sitesmeteo 0 seuilshydro 0 seuilsmeteo 0 modelesprevision 0 evenements 0 courbestarage 0 jaugeages 0 courbescorrection 0 serieshydro 0 seriesmeteo 0 seriesobselab 1 simulations >>> for s in content.simulations: ... print(s.entite.code, s.grandeur) ... print(s.previsions_tend) K1930010 Q dte tend 2016-04-20 06:00:00 moy 657905.029297 min 651244.995117 max 661364.013672 2016-04-20 07:00:00 moy 654122.985840 min 647578.979492 max 657557.983398 2016-04-20 08:00:00 moy 648411.010742 min 637543.029785 max 654010.009766 2016-04-20 09:00:00 moy 644525.024414 min 629979.980469 max 652531.005859 2016-04-20 10:00:00 moy 636773.986816 min 619005.004883 max 646870.971680 2016-04-20 11:00:00 moy 634590.026855 min 614572.021484 max 646533.020020 2016-04-20 12:00:00 moy 621318.969727 min 600044.982910 max 634541.992188 Name: res, dtype: float64 Exemple d'observations météo >>> f = 'data/data/sandre/dataobs_meteo.xml' >>> sandre = _sandre.Sandre(filename=f) >>> content = sandre.read() >>> content Message du 2016-05-13 13:41:56 de version 1.1 Emetteur: Intervenant SANDRE 1537::<sans nom> [0 contact] [None] Destinataire: Intervenant SIRET 13000930100016::<sans nom> [1 contact] [Contact 398::<sans civilite> <sans nom> <sans prenom> [intervenant 13000930100016]] Contenu: 0 intervenants 0 siteshydro 0 sitesmeteo 0 seuilshydro 0 seuilsmeteo 0 modelesprevision 0 evenements 0 courbestarage 0 jaugeages 0 courbescorrection 0 serieshydro 1 seriesmeteo 0 seriesobselab 0 simulations >>> for s in content.seriesmeteo: ... print(s.grandeur.sitemeteo.code, s.grandeur.typemesure) ... print(s.observations) 023209001 RR # Le code météo est forcé sur 9 caractères par libhydro res mth qal qua ctxt statut dte 2016-04-15 12:00:00 0.0 0 16 100.0 0 4 2016-04-15 13:00:00 0.0 0 16 100.0 0 4 2016-04-15 14:00:00 0.0 0 16 100.0 0 4 2016-04-15 15:00:00 4.0 0 16 100.0 0 4 2016-04-15 16:00:00 8.0 0 16 100.0 0 4 2016-04-15 17:00:00 8.0 0 16 100.0 0 4 2016-04-15 18:00:00 2.0 0 16 100.0 0 4 2016-04-15 19:00:00 4.0 0 16 100.0 0 4 2016-04-15 20:00:00 2.0 0 16 100.0 0 4 2016-04-15 21:00:00 2.0 0 16 100.0 0 4 2016-04-15 22:00:00 38.0 0 16 100.0 0 4 2016-04-15 23:00:00 10.0 0 16 100.0 0 4 2016-04-16 00:00:00 24.0 0 16 100.0 0 4 2016-04-16 01:00:00 12.0 0 16 100.0 0 4 2016-04-16 02:00:00 2.0 0 16 100.0 0 4 2016-04-16 03:00:00 2.0 0 16 100.0 0 4 2016-04-16 04:00:00 0.0 0 16 100.0 0 4 2016-04-16 05:00:00 8.0 0 16 100.0 0 4 2016-04-16 06:00:00 14.0 0 16 100.0 0 4 Exemple de Vigicrues >>> f = 'data/webservice/vigicrues/vigicrues_obs_202101291400.xml' >>> sandre = _sandre.Sandre(filename=f) >>> content = sandre.read() >>> content Message du 2021-03-03 08:23:01.013681 de version 1.1 Emetteur: Intervenant SANDRE 1537::<sans nom> [0 contact] [None] Destinataire: Intervenant SANDRE 0::<sans nom> [0 contact] [None] Contenu: 0 intervenants 0 siteshydro 0 sitesmeteo 0 seuilshydro 0 seuilsmeteo 0 modelesprevision 0 evenements 0 courbestarage 0 jaugeages 0 courbescorrection 1 serieshydro 0 seriesmeteo 0 seriesobselab 0 simulations >>> for s in content.serieshydro: ... print(s.entite.code, s.grandeur) ... print(s.observations) K055001010 Q res mth qal cnt statut dte 2021-01-27 12:00:00 51000.0 0 16 0 4 2021-01-27 13:00:00 50700.0 0 16 0 4 2021-01-27 14:00:00 50600.0 0 16 0 4 2021-01-27 15:00:00 50600.0 0 16 0 4 2021-01-27 16:00:00 50400.0 0 16 0 4 2021-01-27 17:00:00 50700.0 0 16 0 4 2021-01-27 18:00:00 50300.0 0 16 0 4 2021-01-27 19:00:00 50700.0 0 16 0 4 2021-01-27 20:00:00 49400.0 0 16 0 4 2021-01-27 21:00:00 48300.0 0 16 0 4 2021-01-27 22:00:00 48800.0 0 16 0 4 2021-01-27 23:00:00 52800.0 0 16 0 4 2021-01-28 00:00:00 54100.0 0 16 0 4 2021-01-28 00:05:00 54100.0 0 16 0 4 2021-01-28 00:10:00 54100.0 0 16 0 4 2021-01-28 00:15:00 54100.0 0 16 0 4 2021-01-28 00:20:00 54100.0 0 16 0 4 2021-01-28 00:25:00 54100.0 0 16 0 4 2021-01-28 00:30:00 54100.0 0 16 0 4 2021-01-28 00:35:00 54100.0 0 16 0 4 2021-01-28 00:50:00 54100.0 0 16 0 4 2021-01-28 00:55:00 54100.0 0 16 0 4 2021-01-28 01:00:00 54100.0 0 16 0 4 2021-01-28 01:05:00 54100.0 0 16 0 4 2021-01-28 01:10:00 54100.0 0 16 0 4 2021-01-28 01:15:00 54100.0 0 16 0 4 2021-01-28 01:20:00 54100.0 0 16 0 4 2021-01-28 01:25:00 54100.0 0 16 0 4 2021-01-28 01:30:00 54100.0 0 16 0 4 2021-01-28 01:35:00 54100.0 0 16 0 4 2021-01-28 01:40:00 54100.0 0 16 0 4 2021-01-28 01:45:00 54100.0 0 16 0 4 2021-01-28 01:50:00 54100.0 0 16 0 4 2021-01-28 01:55:00 54100.0 0 16 0 4 2021-01-28 02:00:00 54100.0 0 16 0 4 See Also -------- Repose sur la libhydro : https://gitlab.com/vigicrues/hydro3/libhydro """ from libhydro.conv import xml as _xml return _xml.Message.from_file(self.filename)
[docs] @staticmethod def check_dtype(dtype): """ Contrôler s'il s'agit bien d'une donnée autorisée. Parameters ---------- dtype : str Type de donnée à contrôler """ try: DATATYPES.index(dtype) except ValueError as ve: raise ValueError(f"Export Sandre '{dtype}' incorrect") from ve
[docs] @staticmethod def process_comsim(xml_comsim): """Extraire le code simulation.""" try: xmlstring = xml_comsim.replace('{', '<').replace('}', '>') except AttributeError: return ComSimul() root = ElementTree.fromstring(xmlstring) try: runtime = dt.strptime(root.find('DtBaseSimul').text, '%Y-%m-%dT%H:%M:%S') except ValueError: runtime = None except AttributeError: runtime = None try: scen_code = root.find('CodeScenarioSimul').text except AttributeError: scen_code = None try: scen_name = root.find('NomScenarioSimul').text except AttributeError: scen_name = None return ComSimul(runtime, scen_code, scen_name)
[docs] @staticmethod def concat(filename=None, filenames=None, runtime=None, sender=None, user=None, target=None): """ Fusionner plusieurs fichiers xml Sandre. Parameters ---------- filename : str Nom du fichier xml à écrire filenames : str Noms des fichiers xml à lire runtime : datetime Date de production de la donnée/prévision sender : str Identifiant de l'emetteur user : str Identifiant du contact target : str Identifiant du destinataire Returns ------- filename : str Nom du fichier xml à écrire """ from libhydro.conv.xml import Message, Scenario from libhydro.core.intervenant import Contact, Intervenant # --------------------------------------------------------------------- # 0- Contrôles # --------------------------------------------------------------------- _exception.check_str(filename) _exception.check_listlike(filenames) _exception.check_str(sender) _exception.check_str(user) _exception.check_str(target) # --------------------------------------------------------------------- # 1- Scénario Sandre # --------------------------------------------------------------------- user = Intervenant(code=user) sender = Contact(code=sender, intervenant=user) target = Intervenant(code=target) xml_scen = Scenario( emetteur=sender, destinataire=target, dtprod=runtime) # --------------------------------------------------------------------- # 2- Lecture des fichiers Sandre # --------------------------------------------------------------------- content = {} attrs = ['intervenants', 'siteshydro', 'sitesmeteo', 'seuilshydro', 'seuilsmeteo', 'modelesprevision', 'evenements', 'courbestarage', 'jaugeages', 'courbescorrection', 'serieshydro', 'seriesmeteo', 'seriesobselab', 'simulations'] for f in filenames: m = Message.from_file(f) for att in attrs: if hasattr(m, att): content.setdefault(att, []) content[att].extend(getattr(m, att)) # --------------------------------------------------------------------- # 5- Message Sandre # --------------------------------------------------------------------- msg = Message(scenario=xml_scen, **content) msg.write(filename, force=True, bdhydro=True) # --------------------------------------------------------------------- # 6- Retour # --------------------------------------------------------------------- return filename
[docs] def write(self, data=None, datatype=None, runtime=None, timedelta=None, sender=None, user=None, target=None): """ Ecrire un fichier xml Sandre. Parameters ---------- data : pandas.DataFrame Tableau de données datatype : str Type de donnée. Seuls les types commençant par 'data' sont autorisés runtime : datetime Date de production de la donnée/prévision timedelta : timedelta Pas de temps de la donnée sender : str Identifiant de l'emetteur user : str Identifiant du contact target : str Identifiant du destinataire Returns ------- filename : str Nom du fichier xml à écrire Notes ----- - si datatype = 'data_obs_hydro', les colonnes du dataframe sont nommées de la façon suivante pour définir les méta-données - 'Location' : code du lieu - 'Varname' : grandeur - si datatype = 'data_obs_meteo', les colonnes du dataframe sont nommées de la façon suivante pour définir les méta-données - 'Location' : code du lieu - 'Varname' : grandeur - si datatype = 'data_fcst_hydro', les colonnes du dataframe sont nommées de la façon suivante pour définir les méta-données - 'Location' : code du lieu - 'Varname' : grandeur - 'Runtime': date de production - 'Model' : code du modèle - 'Scenario' : code du scénario - 'Prob' : nom de la tendance, parmi ['min', 'moy', 'max'] """ from libhydro.conv.xml import Message, Scenario from libhydro.core.intervenant import Contact, Intervenant # --------------------------------------------------------------------- # 0- Contrôles # --------------------------------------------------------------------- _exception.check_dataframe(data) _exception.check_str(datatype) _exception.raise_valueerror( not datatype.startswith('data'), f"Type de données '{datatype}' incompatible") _exception.check_str(self.filename) _exception.check_str(sender) _exception.check_str(user) _exception.check_str(target) if runtime is None: runtime = dt.utcnow() _exception.check_dt(runtime) # --------------------------------------------------------------------- # 1- Scénario Sandre # --------------------------------------------------------------------- user = Intervenant(code=user) sender = Contact(code=sender, intervenant=user) target = Intervenant(code=target) xml_scen = Scenario( emetteur=sender, destinataire=target, dtprod=runtime) # --------------------------------------------------------------------- # 2- DATA OBS HYDRO # --------------------------------------------------------------------- obss = _sandre_obss(data, datatype, runtime) # --------------------------------------------------------------------- # 3- DATA OBS METEO # --------------------------------------------------------------------- mets = _sandre_mets(data, datatype, runtime, timedelta) # --------------------------------------------------------------------- # 4- DATA FCST HYDRO # --------------------------------------------------------------------- sims = _sandre_sims(data, datatype, xml_scen) # --------------------------------------------------------------------- # 5- Message Sandre # --------------------------------------------------------------------- msg = Message(scenario=xml_scen, serieshydro=obss, seriesmeteo=mets, simulations=sims) msg.write(self.filename, force=True, bdhydro=True) # --------------------------------------------------------------------- # 6- Retour # --------------------------------------------------------------------- return self.filename
[docs] @staticmethod def get_types(): """ Renvoyer la liste des données du XML Sandre. Returns ------- list Types de données de la XML Sandre """ return sorted(DATATYPES)
def _sandre_obss(data, datatype, runtime): """Créer une liste de séries d'observation hydrométrique.""" from libhydro.core.sitehydro import Sitehydro, Station from libhydro.core.obshydro import Serie obss = [] if datatype == 'data_obs_hydro': for p in OBS_COLS: if p not in data.columns.names: raise ValueError(f"Méta-donné '{p}' manquante") # Ordre du multi-index data = data.reorder_levels(OBS_COLS, axis=1) for c in data.columns: loc = c[0] varname = c[1] if varname == 'Q' and len(loc) < 10: loc = Sitehydro(code=loc[:8]) mth = 8 else: loc = Station(code=loc[:10]) mth = 0 df = data[c].to_frame().dropna() df.columns = ['res'] df.index.name = 'dte' df['mth'] = mth df['qal'] = 16 df['cnt'] = 0 df['statut'] = 4 obs = Serie( entite=loc, grandeur=varname, observations=df, dtprod=runtime, dtdeb=df.index[0], dtfin=df.index[-1]) obss.append(obs) return obss def _sandre_mets(data, datatype, runtime, timedelta): """Créer une liste de séries d'observation météorologique.""" from libhydro.core.sitemeteo import Grandeur, Sitemeteo from libhydro.core.obsmeteo import Serie mets = [] if datatype == 'data_obs_meteo': for p in OBS_COLS: if p not in data.columns.names: raise ValueError(f"Méta-donné '{p}' manquante") # Ordre du multi-index data = data.reorder_levels(OBS_COLS, axis=1) for c in data.columns: loc = Sitemeteo(code=c[0]) varname = Grandeur(typemesure=c[1], sitemeteo=loc) if timedelta is None: timedelta = 0 df = data[c].to_frame().dropna() df.columns = ['res'] df.index.name = 'dte' df['mth'] = 0 df['qal'] = 16 df['qua'] = 100 df['ctxt'] = 0 df['statut'] = 4 met = Serie(grandeur=varname, observations=df, dtprod=runtime, duree=timedelta) mets.append(met) return mets def _sandre_sims(data, datatype, xml_scen): """Créer une liste de simulations (prévisions avec tendances).""" from libhydro.core.sitehydro import Sitehydro, Station from libhydro.core.modeleprevision import Modeleprevision from libhydro.core.simulation import Simulation sims = [] if datatype == 'data_fcst_hydro': for p in FCST_COLS: if p not in data.columns.names: raise ValueError(f"Méta-donné '{p}' manquante") # Ordre du multi-index data = data.reorder_levels(FCST_COLS, axis=1) # Boucle sur les simulations, éléments communs : # 'Location', 'Varname', 'Runtime', 'Model', 'Scenario' metas = sorted({tuple(c[:-1]) for c in data.columns}) for meta in metas: loc = meta[0] varname = meta[1] if varname == 'Q': loc = Sitehydro(code=loc[:8]) else: loc = Station(code=loc[:10]) model = Modeleprevision(code=meta[3]) df = data.xs(key=meta, axis=1).stack().to_frame() df.index.names = ['dte', 'tend'] df.columns = ['res'] df['incertdte'] = 0 comment = "{ContexteSimul}" comment += "{DtBaseSimul}" + meta[2].strftime( "%Y-%m-%dT%H:%M:%S") + "{/DtBaseSimul}" comment += "{CodeScenarioSimul}" + meta[-1] + \ "{/CodeScenarioSimul}" comment += "{/ContexteSimul}" sim = Simulation( entite=loc, grandeur=varname, modeleprevision=model, # public=True, statut=16, dtprod=meta[2], # intervenant=user, contact=xml_scen.emetteur.contact, intervenant=xml_scen.emetteur.intervenant, previsions_tend=df, commentaire=comment ) sims.append(sim) return sims